Skip to content

Instantly share code, notes, and snippets.

@ph3b
Last active March 19, 2023 13:54
Show Gist options
  • Save ph3b/98b9aeaff4f86527dc5a523f321cac7e to your computer and use it in GitHub Desktop.
Save ph3b/98b9aeaff4f86527dc5a523f321cac7e to your computer and use it in GitHub Desktop.
DRF - ManyToMany, intermediate model and custom save/update
// Assumes members already exist with id 1 and 2.
{
"name": "My group 1",
"members": [
{ "id": 1, "role": "Leader" },
{ "id": 2, "role": "Regular" }
]
}
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
@transaction.atomic
def update(self, instance, validated_data):
GroupMember.objects.filter(group=instance).delete()
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()
instance.__dict__.update(**validated_data)
instance.save()
return instance
@transaction.atomic
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()
group.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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment