Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Update / patch / create nested models in Django Rest framework

I'm using Django 1.6.8, and Django Rest 2.4.4. I have a Person model with separate models for Address and PhoneNumbers.

class Person(models.Model):
    address = models.OneToOneField(Address, blank=True, null=True)
    phoneNumbers = models.ManyToManyField(PhoneNumber, blank=True)

class Address(models.Model):
    address = models.CharField(max_length=50)
    city = models.CharField(max_length=50)
    state = models.CharField(max_length=2)

class PhoneNumber(models.Model):
    number = models.CharField(max_length=15)
    numberType = models.CharField(default='Mobile', max_length=15)

I'm using nested serializers in Django REST framework.

class PersonSerializer(serializers.HyperlinkedModelSerializer):
    id = serializers.Field('id')

    address = AddressSerializer(source='address')
    phoneNumbers = PhoneNumberSerializer(many=True)

This works for GET (I get address and phone numbers as nested json fields), but I need the same for PUT / POST / PATCH. Specifically, for each phone number, I want it to be updated if the id is specified, or created if there is no id in json. And the same for address, all in the same API call.

like image 816
Ognjen Avatar asked Dec 29 '14 11:12

Ognjen


1 Answers

You need to implement your own create() and / or update() methods to support this.

It's explained in the Django Rest doc and it's available since Django Rest 3.0:

The following example demonstrates how you might handle creating a user with a nested profile object.

class UserSerializer(serializers.ModelSerializer):
    profile = ProfileSerializer()

    class Meta:
        model = User
        fields = ('username', 'email', 'profile')

    def create(self, validated_data):
        profile_data = validated_data.pop('profile')
        user = User.objects.create(**validated_data)
        Profile.objects.create(user=user, **profile_data)
        return user

(...)

Because the behavior of nested creates and updates can be ambiguous, and may require complex dependancies between related models, REST framework 3 requires you to always write these methods explicitly. The default ModelSerializer .create() and .update() methods do not include support for writable nested representations.

like image 69
pchiquet Avatar answered Nov 04 '22 22:11

pchiquet