Aldarund
Aldarund

Reputation: 17621

DRF update resource with serializer with source argument

I have the following code.

class UserSerializer(serializers.ModelSerializer):
   fax = serializers.CharField(source='primary_address.fax')

class User(models.Model):
    primary_address = models.OneToOneField(ProfileAddress, verbose_name=_('Primary address'), null=True, related_name='+')

class ProfileAddress(models.Model):
   fax = models.CharField(max_length=255, verbose_name=_('Fax number'), null=True)
   mobile = models.CharField(max_length=255, verbose_name=_('Mobile phone number'), null=True)

When i'm trying to update the User object by sending fax field i will get a error

Cannot assign "{u'fax': u'0555400123457'}": "User.primary_address" must be a "ProfileAddress" instance.

What is the proper way to update such fields, that define source argument that corresponds to the related models. There can be defined more fields on that related model, and they all should be represented in json output as field, not a nested field.

UPDATE In my validated_data.items in serializer update i see following:

 (u'primary_address', {u'city': {u'name': u'Berlin'}, u'fax': u'0555400123457', u'url': None, u'line1': u'Sch\xf6nhauser Allee', u'phone': u'0555400123456', u'postal_code': u'PostalCode object', u'email': u'[email protected]'}),  (u'title', u'Herr')

And obviously the update code from ModelSerializer:

for attr, value in validated_data.items():
    setattr(instance, attr, value)

Will just try to set primary_address attribute with dictionary value, and it will fail.

Upvotes: 1

Views: 2190

Answers (1)

soooooot
soooooot

Reputation: 1759

you should override the update function to update the primary_address.fax by yourself.

class UserSerializer(serializers.ModelSerializer):
    fax = serializers.CharField(source='primary_address.fax')

    def update(self, instance, validated_data):
        fax = validated_data.pop('fax', None)
        super(UserSerializer, self).update(instance, validated_data)
        if fax is not None:
            instance.primary_address.fax = fax
            instance.primary_address.save(update_fields=('fax',))
        return instance

Upvotes: 2

Related Questions