TypeError: Object of type ManyRelatedManager is not JSON serializable in django rest framework

TypeError: Object of type ManyRelatedManager is not JSON serializable in django rest framework

我正在尝试将一些学生添加到老师class,使用他们的 ID 作为主键,但我遇到了上述错误。

我有这样的师生模型

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

在这里,一个教师模型可以有很多学生 class 以及他们的 ID。我使用了一个 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域)。我知道,因为我将 ID 添加到 student_in_class 字段,所以我不应该将它用作 read_only = true,但是我必须使用它,否则它会产生错误。如何解决这个问题?另外,我真的不知道在序列化器中定义哪些字段 class.

更新代码:

class TeacherSerializer(serializers.ModelSerializer):
    # students_in_class = serializers.PrimaryKeyRelatedField(
    #     many = True, read_only= True
    # )
    students_in_class = serializers.ListField(
        source="students_in_class.all",
        child=serializers.PrimaryKeyRelatedField(queryset=Student.objects.all()),
    )
    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['students_in_class']['all']
        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

由于您使用的是 m2m 字段,因此您需要 students_in_class 的 ID 列表。所以解决方案将是这样的。 (免责声明:代码未经测试)。

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 设置为 write_only 并根据需要覆盖序列化程序表示。:

class TeacherSerializer(serializers.ModelSerializer):
    students_in_class = serializers.ListField(
        child=serializers.PrimaryKeyRelatedField(queryset=Student.objects.all()),
        write_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