I'm new to Django and have just started to learn the basics. I have some questions about how to structure the code, how relationships should be written, and where the business logic should live.

I have written a simple app that should do the following:

  1. Store Group and Member entities in a database.
  2. Maintain a many-to-many relationship between groups and members, as well as member role specific to each group.
  3. To create or update a group it should be possible send a request with the json structure shown below.

      "name": "My group 1",
      "members": [
        { "id": 1, "role": "Leader" },
        { "id": 2, "role": "Regular" }

Questions about the code

  1. Am I re-inventing the wheel with the custom update/create code in the GroupSerializer? Does what I'm trying to do already exist in Django and I have just not found the right approach?
  2. Is the update/create logic in the GroupSerializers misplaced? Should this be in the views.py file?
  3. In serializers.py, line 23, is there a better way than using "source=groupmember_set". I feel dirty hardcoding this string. In additional comments are of course welcome.

I appreciate any feedback that can improve the code and my knowledge further!


from __future__ import unicode_literals
from django.db import models

class Member(models.Model):
    name = models.CharField(max_length=50)
    def __unicode__(self):
        return self.name

class Group(models.Model):
    name = models.CharField(max_length=50)
    members = models.ManyToManyField(Member, blank=True, related_name='groups', through="GroupMember")
    def __unicode__(self):
        return self.name

class GroupMember(models.Model):
    member = models.ForeignKey(Member, on_delete=models.CASCADE)
    group = models.ForeignKey(Group, on_delete=models.CASCADE)
    role = models.CharField(max_length=40)
    def __unicode__(self):
        return self.member.name + " " + self.group.name + " - " + self.role


from rest_framework import serializers
from models import Group, Member, GroupMember
from django.db import transaction

class MemberSerializer(serializers.ModelSerializer):

    class Meta:
        model = Member
        fields = ('id', 'name', 'groups')

class GroupMemberSerializer(serializers.ModelSerializer):
    id = serializers.ReadOnlyField(source='member.id')
    name = serializers.ReadOnlyField(source='member.name')

    class Meta:
        model = GroupMember
        fields = ('id', 'name', 'role')

class GroupSerializer(serializers.ModelSerializer):
    members = GroupMemberSerializer(source="groupmember_set", many=True, read_only=True)

    class Meta:
        model = Project
        fields = '__all__'
        depth = 1

    def update(self, instance, validated_data):
        # Ignore the fact that i delete and replace. Will diff in the future
        members = self.initial_data.get("members")
        for member in members:
            id = member.get("id")
            role = member.get("role")
            new_member = Member.objects.get(pk=id)
            GroupMember(group=instance, member=new_member, role=role).save()

        return instance

    def create(self, validated_data):
        group = Group.objects.create(**validated_data)
        if "members" in self.initial_data:
            members = self.initial_data.get("members")
            for member in members:
                id = member.get("id")
                role = member.get("role")
                member_instance = Member.objects.get(pk=id)
                GroupMember(group=group, member=member_instance, role=role).save()
        return project


from rest_framework import viewsets
from models import Group, Member
from serializers import GroupSerializer, MemberSerializer

class GroupViewSet(viewsets.ModelViewSet):
    queryset = Group.objects.all()
    serializer_class = GroupSerializer

class MemberViewSet(viewsets.ModelViewSet):
    queryset = Member.objects.all()
    serializer_class = MemberSerializer
  • 2
    \$\begingroup\$ Thanks for posting this here. It's the first working example I've been able to find on the net for posting nested data with a through model. Mostly working anyway. ;-) \$\endgroup\$
    – shanemgrey
    Dec 19, 2017 at 22:40
  • 1
    \$\begingroup\$ Thank you so much for this code snippet! I have been wondering what I am doing wrong for hours until I found this example! \$\endgroup\$
    – Ratul
    Mar 19, 2018 at 7:05
  • \$\begingroup\$ You don't have to handle nested representations. \$\endgroup\$
    – x-yuri
    Jan 16, 2019 at 18:18

2 Answers 2


Django-organizations is a great way to do this, if you didn't want to reinvent the wheel. Comes with many things I assume you would need in the future out of the box.

  • \$\begingroup\$ Thank you for the suggestion but it wasn't the organization domain specifically that I needed a solution for. More how to implement the relation in general. \$\endgroup\$
    – Matt
    Jan 16, 2019 at 8:42

You could replace source=groupmember_set with source=groups (the related_name of the ManyToMany field). I think it is a little bit cleaner and easier to understand.

One thing I don't understand is, why are you using model = Project in your GroupSerializer class?


Not the answer you're looking for? Browse other questions tagged or ask your own question.