Let's start from the models used in the django docs about the M2M relationship that uses the through argument to point to the model that will act as an intermediary.
class Person(models.Model):
name = models.CharField(max_length=128)
def __unicode__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person,
through='Membership')
def __unicode__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
class Meta:
ordering = ['date_joined']
Assume now I want to have a rest read-write view for the Group model which contains also all the Person inside each group, ordered by date_joined field. The json serialization I would like to obtain is the following (the members are described only with their id):
{
"id": 1,
"name": "U2",
"members": [
20,
269,
134,
12,
]
}
I wrote a serializer:
class GroupSerializer(serializers.ModelSerializer):
members = serializers.SlugRelatedField(source='membership_set',
many=True,
read_only=False,
slug_field='person_id',
required=True)
class Meta:
model = Group
fields = ('id', 'name', 'members')
While for read operations it works well, it doesn't for writing. How should I define the serializer so that, given the above defined serialization, it will proceed by:
From here you can see that what you are trying to do works only for read operations. This is a common problem for DRF, as stated by its creator, Tom Christie, in this comment.
Also, for the JSON serialization that you want, it is recommended to use a PK related field, as shown here, though that won't help with creation of the Group object and adding of members. You will have to write that code yourself.
Hope this helps.
Edit
Code snippet for adding each person to the Group by creating Memberships:
def post_save(self, obj, created=False):
# obj represents the Group object
if created:
# Test to see if the Group was successfully created
members = self.request.DATA.get('members', None)
if members not None:
for id in members:
person = Person.objects.get(id=id)
membership, m_created = Membership.objects.get_or_create(person=person, group=obj)
# Here you can use m_created to see if the membership already existed and to do whatever else you need.
This implementation assumes that you have declared your date_joined with auto_now. If not, you should also pass it in as a parameter.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With