英文:
django rest framework serializer, create an object to encapsulate some model field
问题
我有一个类似这样的序列化器:
class ListingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Listing
        fields = '__all__'
我的Listing模型有一些字段:name,price,description,street_address,postal_code,city等。
我希望我的序列化器返回一个像这样的对象:
{
    "name": "Prestige",
    "price": 12,
    "description": "lorem ipsum",
    "address": {
        "street": "123 Main St",
        "city": "New York",
        "state": "NY",
        "zip": "10001"
    },
    ...
}
而不是基本的:
{
    "name": "Prestige",
    "price": 12,
    "description": "lorem ipsum",
    "street": "123 Main St",
    "city": "New York",
    "state": "NY",
    "zip": "10001",
    ...
}
我想要封装所有的 "address" 字段到我的响应中的 "address" 对象中。
英文:
I have a serializer which looks like this:
class ListingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Listing
        fields = '__all__'
My Listing model have some field: name, price, description, etc.., street_address, postal_code, city, etc...
I would like my serializer to return an object like this:
{
    "name": "Prestige",
    "price": 12,
    "description": "lorem ipsum",
    "address": {
        "street": "123 Main St",
        "city": "New York",
        "state": "NY",
        "zip": "10001"
    },
    ...
}
instead of the basic:
{
    "name": "Prestige",
    "price": 12,
    "description": "lorem ipsum",
    "street": "123 Main St",
    "city": "New York",
    "state": "NY",
    "zip": "10001"
    ...
}
What I want is encapsulate all "address" field into an "address" object in my response.
答案1
得分: 1
第一种选择是在你的序列化器上覆盖.to_representation:
serializers.py
class ListingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Listing
        fields = '__all__'
    def to_representation(self, instance):
        representation = super().to_representation(instance)
        address = {}
        address['street'] = representation.pop('street')
        address['city'] = representation.pop('city')
        address['state'] = representation.pop('state')
        address['zip'] = representation.pop('zip')
        representation['address'] = address
        return representation
或者
另一种选择:
如果可以更改你的模型,也许更好的选择是添加一个Address 模型,并将其与 Listing 关联:
models.py
class Address(models.Model):
    street = models.CharField(max_length=100)
    city = models.CharField(max_length=20)
    state = models.CharField(max_length=5)
    zip = models.CharField(max_length=15)
class Listing(models.Model):
    name = models.CharField(max_length=255)
    price = models.IntegerField()
    description = models.CharField(max_length=255)
    address = models.ForeignKey(Address, on_delete=models.DO_NOTHING, related_name='listings')
serializers.py
class AddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = Address
        exclude = ['id']
class ListingSerializer(serializers.ModelSerializer):
    address = AddressSerializer()
    class Meta:
        model = Listing
        fields = ['name', 'price', 'description', 'address']
英文:
First option is to override .to_representation on your serializer:
serializers.py
class ListingSerializer(serializers.ModelSerializer):
    class Meta:
        model = Listing
        fields = '__all__'
    def to_representation(self, instance):
        representation = super().to_representation(instance)
        address = {}
        address['street'] = representation.pop('street')
        address['city'] = representation.pop('city')
        address['state'] = representation.pop('state')
        address['zip'] = representation.pop('zip')
        representation['address'] = address
        return representation
<h2> Alternatively </h2>
If it is possible to change your models, maybe the better option is to add an Address and associate it with Listing:
models.py
class Address(models.Model):
    street = models.CharField(max_length=100)
    city =models.CharField(max_length=20)
    state = models.CharField(max_length=5)
    zip = models.CharField(max_length=15)
class Listing(models.Model):
    name = models.CharField(max_length=255)
    price = models.IntegerField()
    description = models.CharField(max_length=255)
    address = models.ForeignKey(Address, on_delete=models.DO_NOTHING, related_name='listings')
serializers.py
class AddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = Address
        exclude = ['id']
class ListingSerializer(serializers.ModelSerializer):
    address = AddressSerializer()
    class Meta:
        model = Listing
        fields = ['name', 'price', 'description', 'address']
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论