5

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.

Ognjen
  • 2,508
  • 2
  • 31
  • 47

1 Answers1

11

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.

pchiquet
  • 3,097
  • 1
  • 13
  • 15
  • Thank you, but I'm using Rest 2.4.4. I will update the question. – Ognjen Jan 04 '15 at 18:52
  • 1
    In this case, you should write custom views. You can extend DRF APIViews (UpdateAPIView, CreateAPIView, etc.) by writing custom post / put / patch methods. – pchiquet Jan 05 '15 at 08:52
  • Note, the `create` method should be indented back and part of the class `UserSerializer` and not `Meta`. see http://www.django-rest-framework.org/api-guide/relations/#writable-nested-serializers – Aleck Landgraf Mar 11 '16 at 01:38
  • indeed, I fixed the indentation – pchiquet Mar 11 '16 at 13:56