You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DRF可写嵌套序列化器报错‘This field is required.’求排查

DRF可写嵌套序列化器出现"options字段必填"错误的原因及解决方法

在使用Django REST Framework(DRF)创建带选项的测试试题时,提交了包含options数组的JSON数据,但在Postman和测试用例中均收到验证错误,提示options字段必填。

提交的数据:

{
    "lesson": 2,
    "question": "This is our first question?",
    "options": [
        {
            "option": "Option 1",
            "correct": True
        },
        {
            "option": "Option 2 ",
            "correct": False
        },
        {
            "option": "Option 3",
            "correct": True
        }
    ]
}

错误响应:

{
    "options": [
        "This field is required."
    ]
}

相关代码:

models.py

class Question(models.Model):
    lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE, related_name='questions')
    question = models.CharField('lesson name', max_length=120)


class Option(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE, related_name='options')
    option = models.CharField('test option', max_length=100)
    correct = models.BooleanField(default=False)

views.py

class QuestionAPIView(generics.CreateAPIView):
    queryset = Question.objects.all()
    serializer_class = QuestionSerializer

serializers.py

class OptionSerializer(serializers.ModelSerializer):

    class Meta:
        model = Option
        fields = ('option', 'correct')


class QuestionSerializer(serializers.ModelSerializer):
    options = OptionSerializer(many=True)

    class Meta:
        model = Question
        fields = ('lesson', 'question', 'options')

    def create(self, validated_data):
        options_data = validated_data.pop('options')
        question = Question.objects.create(**validated_data)
        for option_data in options_data:
            Option.objects.create(question=question, **option_data)
        return question

错误原因

错误的核心是DRF中嵌套序列化器字段默认是只读的:

  • 在QuestionSerializer中,options = OptionSerializer(many=True)这个嵌套字段默认标记为read_only=True,DRF处理输入数据(反序列化)时会忽略提交的options字段,不会将其解析到validated_data中。
  • 同时该字段的required属性默认是True,DRF会验证该字段是否存在,但因为它是只读的,DRF无法识别到你提交的options数据,因此判定该字段缺失,返回必填错误。

解决方案

修改QuestionSerializer中的options字段定义,显式设置read_only=False,让DRF允许该字段接收输入数据:

class QuestionSerializer(serializers.ModelSerializer):
    # 添加read_only=False,允许嵌套字段接收输入
    options = OptionSerializer(many=True, read_only=False)

    class Meta:
        model = Question
        fields = ('lesson', 'question', 'options')

    def create(self, validated_data):
        options_data = validated_data.pop('options')
        question = Question.objects.create(**validated_data)
        for option_data in options_data:
            Option.objects.create(question=question, **option_data)
        return question

如果希望options字段只在创建/更新时接收输入,而不在返回的序列化数据中展示,可以改为设置write_only=True:

options = OptionSerializer(many=True, write_only=True)

修改后,DRF会正确解析提交的options数据,create方法也能正常取出options_data创建关联的Option实例。

内容的提问来源于stack exchange,提问作者Anna Berezko

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 20:40:34