TypeError: Объект типа ManyRelatedManager не является JSON сериализуемым в django rest framework

Я пытаюсь добавить некоторых учеников в класс учителя, используя их идентификаторы в качестве первичного ключа, но получаю вышеуказанную ошибку.

У меня есть модели таких учителей и учеников.

class Student(TimeStampAbstractModel):
    user = models.OneToOneField(User, related_name="student", on_delete=models.CASCADE)
    college_name = models.CharField(max_length=255, default="", blank=True)
    address = models.CharField(max_length=255, default="", blank=True)

    def __str__(self):
        return self.user.name

class Teacher(TimeStampAbstractModel):
    user = models.OneToOneField(User, related_name="teacher", on_delete=models.CASCADE)
    address = models.CharField(max_length=255, default="", blank=True)
    students_in_class = models.ManyToManyField(Student,related_name="teacher")

    def __str__(self):
        return self.user.name

Здесь модель учителя может иметь много учеников в классе с их идентификаторами. Я использовал вызов put api для добавления учеников к учителю в один клик.

Мое мнение:

from rest_framework import status
class AddtoClassView(APIView):
    

    def put(self,request,pk,*args,**kwargs):
        id =pk
        teacher = Teacher.objects.get(id=id)
        serializer = TeacherSerializer(teacher,data=request.data)
        if serializer.is_valid():
            serializer.save()
            print("iam if")
            return Response({
                "message":"Student has been added to class.",
                "data": serializer.data
            },status=status.HTTP_200_OK)

        # else:
        print("iam else")
        return Response(serializer.data)

Мой сериализатор:

class TeacherSerializer(serializers.ModelSerializer):
    students_in_class = serializers.PrimaryKeyRelatedField(
        read_only= True
    )
    address = serializers.CharField(required=False)
    # user = serializers.PrimaryKeyRelatedField(read_only=True)

    class Meta:
        model = Teacher
        fields = ["address","students_in_class"]
        # fields = '__all__'

    def update(self, instance, validated_data):
        instance.address = validated_data.get("address")
        instance.save()
        stu = validated_data.get("students_in_class")
        print(stu)
        if stu is not None:
            print("iam stu")
            instance.students_in_class.add(stu)
        instance.save()
        super(TeacherSerializer,self).update(instance, validated_data)
        return instance

Здесь я использовал students_in_class как pk поле (я все еще не понял, когда использовать integarfield и когда использовать pk поле). Я знаю, что поскольку я добавляю идентификаторы в поле student_in_class, я не должен использовать его как read_only = true, однако я должен был использовать, иначе оно выдает ошибку. Как решить эту проблему? Также я не знаю, какие поля должны быть определены в классе сериализатора.

<<<Поскольку вы используете поле m2m, вам нужен список идентификаторов для

. Поэтому решение будет примерно таким. (Оговорка: код не тестировался).students_in_class

class TeacherSerializer(serializers.ModelSerializer):
    students_in_class = serializers.ListField(
        source="students_in_class.all", 
        child=serializers.PrimaryKeyRelatedField(queryset=Student.objects.all()),
    )

Ошибка сериализации будет решена, потому что теперь вы включили students_in_class.all в качестве источника. Вам нужно получить доступ к данным с помощью чего-то вроде этого: validated_data['students_in_class']['all']

Если вы хотите сериализовать ваш вывод другим способом, вы также можете установить students_in_class как read_only и переопределить представление сериализатора по мере необходимости.:

class TeacherSerializer(serializers.ModelSerializer):
    students_in_class = serializers.ListField(
        child=serializers.PrimaryKeyRelatedField(queryset=Student.objects.all()),
        read_only=True
    )
    # your code

    def to_representation(self, instance):
        ret = super().to_representation(instance)
        ret['students_in_class'] = StudentSerializer(instance.students_in_class.all(), many=True).data
        return ret

Сработал следующий код:

class TeacherSerializer(serializers.ModelSerializer):
    students_in_class = serializers.PrimaryKeyRelatedField(
        many = True,queryset=Student.objects.all()
    )
    address = serializers.CharField(required=False)

    class Meta:
        model = Teacher
        fields = ["address","students_in_class"]


    def update(self, instance, validated_data):
        instance.address = validated_data.get("address")
        instance.save()
        stu = validated_data.pop("students_in_class")

        for stus in stu:
            instance.students_in_class.add(stus)

        instance.save()
        super(TeacherSerializer,self).update(instance, validated_data)
        return instance
Вернуться на верх