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
, однако я должен был использовать, иначе оно выдает ошибку. Как решить эту проблему? Также я не знаю, какие поля должны быть определены в классе сериализатора.
. Поэтому решение будет примерно таким. (Оговорка: код не тестировался).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