Django DRF(De-)Serializer对我来说不起作用?

6 浏览
0 Comments

Django DRF(De-)Serializer对我来说不起作用?

我遇到了一个我不理解的案例。

我有两个相关的模型:

class Course(models.Model):
  code = models.CharField(max_length=10, default='')
  semester = models.CharField(max_length=10, default='')
  class Meta:
        unique_together = [['code', 'semester']]
class StudentWork(models.Model):
  code = models.CharField(max_length=10, default='')
  course = models.ForeignKey(Course,on_delete=models.CASCADE, related_name='student_works')
  deadline = models.DateTimeField(blank=True)

在StudentWorkSerializer中,我想将course字段扩展为[code, semester]:

class CourseNaturalSerializer(serializers.ModelSerializer):
    class Meta:
        model = Course
        fields = ['code', 'semester']
class StudentWorkWithCourseSerializer(serializers.ModelSerializer):
    course = CourseNaturalSerializer(read_only=True)
    class Meta:
       model = StudentWork
       fields = ['code', 'course', 'deadline']

这对于GET方法很好用,例如我收到这样的结果:

{'code': 'HW1', 'course': {'code': 'T101', 'semester': 'S20'}, 'deadline': '2020-09-04T23:59:00+03:00'}

但是对于POST方法不起作用:

POST /studentworks json=dict(code='HW2', course={"code": "T101", "semester": "S20"}, deadline="2020-09-04T23:59")

堆栈跟踪中显示:

django.db.utils.IntegrityError: NOT NULL constraint failed: botdb_studentwork.course_id

所以在我看来,{"code": "T101", "semester": "S20"} 无法反序列化为Course对象,并且它的id没有传递给StudentWork的create方法?

我该怎么办?

提前感谢!

更新:

有人问我关于相关字段序列化器上的read_only=True是否有意义?

如果我不设置它,我会得到:

'{"course":{"non_field_errors":["The fields code, semester must make a unique set."]}}'

这让我觉得它想要为我创建一个新的Course(因为code和semester被声明为unique_together),但我不想要这样。

如果我在POST数据中更改了例如semester为S21,我会得到:

AssertionError: The `.create()` method does not support writable nested fields by default.
Write an explicit `.create()` method for serializer `botdb.serializers.StudentWorkWithCourseSerializer`, or set `read_only=True` on nested serializer fields.

所以这就是我困惑的地方 - 我无法弄清楚如何防止它尝试创建一个新的Course,而只是使用一个现有的相关字段。

0
0 Comments

问题的原因:用户想要通过传递课程的代码和学期组合来创建一个新的课程对象,但是Django DRF的(De-)Serializer在这种情况下无法正常工作。

解决方法:用户可以考虑只传递course_id来创建新的课程对象。当然,这种方法是可行的。然而,用户仍然希望能够通过传递代码和学期组合来创建课程对象。

代码示例:

class CourseSerializer(serializers.Serializer):
    code = serializers.CharField()
    semester = serializers.CharField()
    def create(self, validated_data):
        course = Course.objects.create(
            code=validated_data['code'],
            semester=validated_data['semester']
        )
        return course

class CourseView(APIView):
    def post(self, request, format=None):
        serializer = CourseSerializer(data=request.data)
        if serializer.is_valid():
            course = serializer.save()
            # do something with the created course object
            return Response(status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

通过以上代码示例,用户可以通过传递代码和学期组合来创建课程对象,并且Django DRF的(De-)Serializer可以正常工作。

0