How to work with M2M relationships in django-rest

Let's start with the models used in the django documentation on the M2M relationship, which uses a pass-through argument to point to a 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'] 

Suppose now I want to get a read-write rest for a group model, which also contains all the people within each group, sorted by date_joined field . I would like to get json serialized (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') 

Although it works well for read operations, it does not for write operations. How do I define a serializer so that, given the serialization described above, it continues:

  1. Create a group object
  2. Add each member to the group (by creating the Membership object)
+5
source share
1 answer

From here you can see that what you are trying to do only works for read operations. This is a common problem for DRF, as its creator Tom Christie stated in this comment.

In addition, to serialize the JSON you want, it is recommended that you use the PK-related field, as shown here , to help with creating the Group object and adding members. You will have to write this code yourself.

Hope this helps.

Edit

A snippet of code to add each person to a group by creating a membership:

 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 specified your date_joined with auto_now. If not, you should also pass it as a parameter.

+2
source

Source: https://habr.com/ru/post/971835/


All Articles