Django Rest Framework - Nested Serialization not working as expected

馋奶兔 提交于 2020-06-09 17:23:27

问题


While using Django-REST-Framework, I am not able to display selected fields in a nested serialized object.

I am correctly able to serialize the entirety of the Address model, but I want only a few fields from Address, nested in my serialized Outlet. There is a

Got AttributeError when attempting to get a value for field outlet_address on serializer OutletSerializer. The serializer field might be named incorrectly and not match any attribute or key on the Outlet instance. Original exception text was: 'Outlet' object has no attribute 'outlet_address'.

api_v1/models.py

class Address(models.Model):
    building = models.CharField(_("shop number, floor & building"), max_length=128)
    street = models.CharField(_("street"), max_length=128, blank=True)
    area = models.ManyToManyField(Area, related_name='address')
    city = models.ForeignKey(City, related_name='address')
    pin_code = models.CharField(_("PIN code"), max_length=6, default="")

    def __unicode__(self):
        return self.building + " " + self.street + " ..."


class Outlet(models.Model):
    name = models.CharField(max_length=100, blank=True)
    chain = models.ForeignKey(Chain, related_name='outlet', blank=True, null=True)
    organization = models.ForeignKey(Organization, blank=True, null=True)
    address = models.OneToOneField(Address, related_name='outlet_address')
    thumbnail = AjaxImageField(upload_to='thumbnails',
                               max_height=200,  #optional
                               max_width=200,  # optional
                               crop=True)  # optional
    date_created = models.DateTimeField(_('date created'), default=timezone.now)

    def __unicode__(self):
        return self.name

api_v1/serializers.py

from rest_framework import serializers
from api_v1.models import Outlet, Address

class AddressSerializer(serializers.ModelSerializer):
    #address_area = AreaSerializer(many=False)

    class Meta:
        model = Address
        fields = ('building', 'street',)
        depth = 3


class OutletSerializer(serializers.ModelSerializer):
    outlet_address = AddressSerializer(many=False)
    #area = serializers.CharField(source='address.area') #multiple levels of nesting?

    class Meta:
        model = Outlet
        fields = ('id', 'name', 'thumbnail', 'outlet_address')
        # fields = ('id', 'name', 'thumbnail', 'address') # this works
        depth = 3

At this point, it is unable to find the outlet_address attribute in the Outlet model while I expect it should be able to in the serializer.

Got AttributeError when attempting to get a value for field outlet_address on serializer OutletSerializer. The serializer field might be named incorrectly and not match any attribute or key on the Outlet instance. Original exception text was: 'Outlet' object has no attribute 'outlet_address'.

As described on other answers, I have tried:

  1. adding many= to the ModelSerializer
  2. adding related_name= to all Models

回答1:


Try this:

from rest_framework import serializers
from api_v1.models import Outlet, Address

class AddressSerializer(serializers.ModelSerializer):

    class Meta:
        model = Address
        fields = ('building', 'street',)
        depth = 3


class OutletSerializer(serializers.ModelSerializer):
    address = AddressSerializer(many=False) # make it address, not outlet_address

    class Meta:
        model = Outlet
        fields = ('id', 'name', 'thumbnail', 'address') # make this address as well, not outlet_address
        depth = 3

The reason I would make the changes above is because the Outlet model does not have an attribute called "outlet_address", it has an attribute called "address".

See here for a similar issue: Django Rest framework keeps returning error on nested relationship




回答2:


Additionally to the other answers, I would like to add the following in case somebody lands here too.

The nested serialization requires the field name to be in the model fields in order to work.

In case that we need a reverse relation, then obviously there will be no such field in the model fields.

For example, with the particular models in the question, this would happen if we needed to reference all outlets in the address serializer.

Therefore we need to: (a) Either specify a related_name to the foreign key of the other model. This is where we would use outlet_address, as this is the related name of address field in outlet model.

Or (b) if no related name then use the default Django name, appending _set to the model name (eg outlet_set.




回答3:


Model Outlet has an "address" field, not an outlet_address. I would advise to set your serializer like this:

class OutletSerializer(serializers.ModelSerializer):
    address = AddressSerializer(many=False)

    class Meta:
        model = Outlet
        fields = ('id', 'name', 'thumbnail', 'address')
        depth = 2


来源:https://stackoverflow.com/questions/33227297/django-rest-framework-nested-serialization-not-working-as-expected

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!