Skip to content
Advertisement

How to add data to Many-To-Many field in Django DRF

I’m new to Django DRF, trying to have a sports school project done. I have a model for coaches, classes and students. Here is a stripped version to keep it simple and easy:

class Student (models.Model):
    first_name = models.CharField(max_length = 50)
    last_name = models.CharField(max_length = 50)

    def __str__(self):
        return f'{self.first_name} {self.last_name}'

 class Coach (models.Model):
    first_name = models.CharField(max_length = 50)
    last_name = models.CharField(max_length = 50)

    def __str__(self):
        return f'{self.first_name} {self.last_name}'

 class ClassDetails (models.Model):
    class_name = models.CharField(max_length = 50)
    class_coach = models.ForeignKey(Coach, related_name='coach_classes')
    class_members = models.ManyToMany(Student, related_name='student_classes')

    def __str__(self):
        return self.class_name

In order to list/add students to the class, I’m using the following serializer:

class ClassDetailsSerializer(serializers.ModelSerializer):
class Meta:
    model = ClassDetails
    fields = ['id','class_name', 'class_coach', 'class_members]
    read_only_fields = ('id', 'class_name', 'class_coach')

Getting the data is working ok. Also, adding a coach is working fine, what is really giving me a hard time is adding a class member. I’m using the following view:

def member_add(self, request):
    my_class = ClassDetails.objects.get(pk = request.data['id']
    serializer = ClassDetailsSerializer(my_class, data=request.data)
    if serializer.is_valid():
        serializer.save()
        return Response('Member added', status.HTTP_201_CREATED)
    return Response(serializer.errors, status.HTTP_406_NOT_ACCEPTABLE)

I’m sending a POST body like:

{
    "id": 2, <- class id
    "class_members": [20] <- student's id to add to the class members
}

The problem is no matter how many students in the class, the above will remove them all and put student id 20 instead.

  • How can I keep the current students and only ADD the new id to them?
  • How can I as well remove a student’s id without deleting the whole data in class_members field?

Thanks!

Advertisement

Answer

I would say to define your model in a different way, here is an example –

First define your Class Detail like –

 class ClassDetails (models.Model):
    class_name = models.CharField(max_length = 50)

    def __str__(self):
        return self.class_name

then define your Student such as –

class Student (models.Model):
    first_name = models.CharField(max_length = 50)
    last_name = models.CharField(max_length = 50)
    classDetail = models.ForeignKey(ClassDetails)

    def __str__(self):
        return f'{self.first_name} {self.last_name}'

and finally your coach as –

class Coach (models.Model):
    first_name = models.CharField(max_length = 50)
    last_name = models.CharField(max_length = 50)
    classDetail = models.ForeignKey(ClassDetails)
    
    def __str__(self):
        return f'{self.first_name} {self.last_name}'

this way you can use the nested feature – now your student is always linked to a class and also your coach is linked to your class.

Now you can say each class can have multiple students and also each class can have multiple coach. Now if Coach is unique per class you can write Coach Modals as –

class Coach (models.Model):
    first_name = models.CharField(max_length = 50)
    last_name = models.CharField(max_length = 50)
    classDetail = models.OneToOneField(ClassDetails)

Editing My answer based on inputs —

to add a new id in manytomany type field first you will have to create a student for eg.

s = Student.objects.create()

and then do something like

my_class = ClassDetails.objects.get(pk = request.data['id'])

to get the correct instance of classdetail and then do something like –

my_class.class_members.add(s)

to add a new student to your manytomany field in ClassDetails

You can customize it according to your needs, hoping this helps you.

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement