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

Django REST Framework报错:'Quiz'对象无'question'属性,如何关联模型?

问题原因

错误核心是反向关联名称不匹配:Question模型通过外键关联Quiz时,Django默认生成的反向关联属性名为question_set,但你在QuizSerializer中指定了source='question',导致序列化器尝试访问Quiz实例不存在的question属性,抛出AttributeError。

解决方法

推荐使用第一种方法(更直观,符合代码命名习惯):

方法一:给外键添加related_name

修改Question模型的外键字段,显式指定反向关联名称为questions,让Quiz实例可以直接通过quiz.questions访问关联问题:

class Question(models.Model):
    text = models.TextField()
    # 添加related_name='questions',指定反向关联名称
    quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE, related_name='questions')

    def __str__(self):
        return self.text

同时修正QuizSerializer的代码:

  • 移除多余的source='question'配置(因为related_name已与字段名questions一致)
  • 调整create方法中从validated_data取出数据的键为questions(匹配请求体和序列化器字段名)
class QuizSerializer(serializers.ModelSerializer):
    questions = QuestionSerializer(many=True)

    class Meta:
        model = Quiz
        fields = ['title', 'topic', 'difficulty', 'questions', 'created_by']

    def create(self, validated_data):
        # 取出请求体中的questions数据
        questions_data = validated_data.pop('questions')
        quiz = Quiz.objects.create(**validated_data)

        for question_data in questions_data:
            choices_data = question_data.pop('choices')
            question = Question.objects.create(quiz=quiz, **question_data)

            for choice_data in choices_data:
                Choice.objects.create(question=question, **choice_data)

        return quiz

方法二:不修改模型,调整序列化器配置

如果不想修改模型,可以将序列化器的source改为Django默认的反向关联名question_set,同时调整create方法中取出数据的键:

class QuizSerializer(serializers.ModelSerializer):
    # 使用默认反向关联名question_set作为数据源
    questions = QuestionSerializer(source='question_set', many=True)

    class Meta:
        model = Quiz
        fields = ['title', 'topic', 'difficulty', 'questions', 'created_by']

    def create(self, validated_data):
        # 对应source的键,取出question_set数据
        questions_data = validated_data.pop('question_set')
        quiz = Quiz.objects.create(**validated_data)

        for question_data in questions_data:
            choices_data = question_data.pop('choices')
            question = Question.objects.create(quiz=quiz, **question_data)

            for choice_data in choices_data:
                Choice.objects.create(question=question, **choice_data)

        return quiz
额外修复

注意Choice模型的__str__方法存在错误:模型中没有text字段,应改为返回options:

class Choice(models.Model):
    options = models.TextField()
    is_correct = models.BooleanField(default=False)
    question = models.ForeignKey(Question, on_delete=models.CASCADE)

    def __str__(self):
        return self.options

内容的提问来源于stack exchange,提问作者kitty francis

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 20:57:28