0

I have problem with saving instance Live_In Nested Serializers in Django Rest Framework. Hope your guys help me! I think just a basic issue.

My Serializers:

I think it comes error when I write saving instance

class CityLiveInSerializer(ModelSerializer):
    country = CharField(required=False, source='country.name')
    class Meta:
        model = City
        fields = [
            'name',
            'slug',
            'country'
        ]    

class UserEditSerializer(ModelSerializer):
    live_in = CityLiveInSerializer(source='profile.live_in')
    about = serializers.CharField(source='profile.about')
    class Meta:
        model = User
        fields = [
            'username',
            'live_in',
            'about',
        ]

    def update(self, instance, validated_data):
        instance.username = validated_data.get('username', instance.username)
        instance.save()
        # Update Serializers Profile
        if (validated_data.get('profile') is not None):
            profile_data = validated_data.pop('profile')
            profile = instance.profile
            profile.about = profile_data.get('about', profile.about)
            profile.save()

        if (validated_data.get('live_in') is not None):
          live_in_data = validated_data.pop('live_in')
          try:
              city = City.objects.get(name=live_in_data['name'])
          except City.DoesNotExist:   
              city = City.objects.create(**live_in_data)
          instance.profile.live_in = city
          instance.profile.save()
        return instance

My City Model (Live_in)

class City(BaseCity):
    class Meta(BaseCity.Meta):
        swappable = swapper.swappable_setting('cities', 'City')

class BaseCity(Place, SlugModel):
    name = models.CharField(max_length=200, db_index=True, verbose_name="standard name")
    country = models.ForeignKey(swapper.get_model_name('cities', 'Country'), related_name='cities', null=True, blank=True)

My Profile Model

class Profile(models.Model):
    # Extend User
    user = models.OneToOneField(User, unique=True)
    about = models.TextField(max_length=1000, default='', blank=True, null=True)
    live_in = models.ForeignKey(City, null=True, blank=True, related_name="live_in")

Data sent by Postman (Json)

{ "live_in": { "name": "Encamp" } }

TraceError:

File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/rest_framework/serializers.py" in data 263. self._data = self.to_representation(self.instance)

File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/rest_framework/serializers.py" in to_representation 488. attribute = field.get_attribute(instance)

File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/rest_framework/fields.py" in get_attribute 463. raise type(exc)(msg)

Exception Type: AttributeError at /api/v1/users/account/edit/ Exception Value: Got AttributeError when attempting to get a value for field live_in on serializer UserEditSerializer. The serializer field might be named incorrectly and not match any attribute or key on the User instance. Original exception text was: 'User' object has no attribute 'live_in'.

2
  • 1
    Can you add user and profile models? Commented Jan 14, 2018 at 10:47
  • It's you again ^^. Added Commented Jan 14, 2018 at 10:56

1 Answer 1

2

First of all you dont need many=True in this case. It required for related objects list, but you will pass only one city. Secondly live_in is attribute of profile model so you need to update profile and add source argument:

live_in = CityLiveInSerializer(source="profile.live_in")

def update(self, instance, validated_data):
    instance.username = validated_data.get('username', instance.username)
    instance.save()
    # Update Serializers Profile
    if (validated_data.get('profile') is not None):
        profile_data = validated_data.pop('profile')
        profile = instance.profile
        profile.about = profile_data.get('about', profile.about)
        if (profile_data.get('live_in') is not None):
            live_in_data = profile_data.pop('live_in')
            try:
                city = City.objects.get(name=live_in_data["name"])
            except City.DoesNotExist:   
                city = City.objects.create(**live_in_data)
        profile.live_in = city 
        profile.save()

    return instance

In this case you need to allow create city without country, so you need to add null=True, blank=True to country attribute:

class BaseCity(Place, SlugModel):
    name = models.CharField(max_length=200, db_index=True, verbose_name="standard name")
    country = models.ForeignKey(swapper.get_model_name('cities', 'Country'),
                            related_name='cities', null=True, blank=True)
Sign up to request clarification or add additional context in comments.

6 Comments

null=True, blank=True for Country will fix it but how if I want to data response have Country Data?
@FeedGit in this case you need to add one more level to you data: { "live_in": { "name": "Encamp", "country": {"name": "CountryName"} }. This mean you need to create another serializer CountrySerializer and add it to CityLiveInSerializer. Also you need to override CityLiveInSerializer's create and update methods like you did in UserEditSerializer. P.S. Yep it's me, hello again:)
Please take a look in my new code above with Traceback!
@FeedGit or you can allow users only to use existing in DB countries. In this case you dont need nested relation. Users can only send country id: { "live_in": { "name": "Encamp", "country": "1"}
@FeedGit I think it should be live_in = CityLiveInSerializer(source="profile.live_in') Check updates.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.