I am trying to create a reference app in DRF 3 to demonstrate a nested serializer that can create/update models. The sample code below bombs with "*create() argument after ** must be a mapping, not list*" when trying to create the nested models. It is also no clear to me how I'd handle the .update() as in some cases I just want to be establish additional relationships (Persons).
The sample models:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
class Group(models.Model):
name = models.CharField(max_length=128)
persons = models.ManyToManyField(Person, through='Membership')
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
And the serializers and viewsets:
from rest_framework.serializers import ModelSerializer
from rest_framework.viewsets import ModelViewSet
from app.models import Group, Person
class PersonSerializer(ModelSerializer):
class Meta:
model = Person
class GroupSerializer(ModelSerializer):
persons = PersonSerializer(many=True)
def create(self, validated_data):
persons = validated_data.pop('persons')
group = Group.objects.create(**validated_data)
if persons: # Bombs without this check
Person.objects.create(group=group, **persons) # Errors here
return group
class Meta:
model = Group
class PersonModelViewSet(ModelViewSet):
serializer_class = PersonSerializer
queryset = Person.objects.all()
class GroupModelViewSet(ModelViewSet):
serializer_class = GroupSerializer
queryset = Group.objects.all()
I am trying to POST some JSON that inserts a Group with two (related) Persons:
{
"persons": [
{ "name" : "name 1" },
{ "name" : "name 2" }
],
"name": "group name 1"
}
I have no clue if there is an easier way, but the only way I managed to get this to work is to reference the 'through' model "memberships" in the Group serializer and write custom code for .create() and .update(). This seems like a lot of work to just set M2M FK's. If someone knows a better way I'd love to hear it.
So you can create a new Group with related Person(s) using:
Use
PrimaryKeyRelatedField
shown here:http://www.django-rest-framework.org/api-guide/relations/#primarykeyrelatedfield
Create each person first, for example. Person with ID 1, Name = "Bob". Person with ID 2, Name = "Tim". Then post them to the REST Endpoint using their
primary keys
So:Now the people that you had created prior, are part of that Group.