Django REST 框架:NOT NULL 约束失败

时间:2021-07-28 09:28:58

标签: python django django-models django-rest-framework

我知道有关于 Django Rest Framework 的答案,但我找不到解决我的问题的方法。

我在 Django REST Framework 中有以下设置:

models.py:

class Variant(models.Model):
    variant = models.CharField(max_length=30)

class Question(models.Model):
    question = models.CharField(max_length=250)
    multiple = models.BooleanField(default=False)
    variants = models.ForeignKey(Variant, db_index=True, on_delete=models.CASCADE)
    answer = models.CharField(max_length=30)


class Quiz(models.Model):
    name = models.CharField(max_length=250)
    description = models.TextField()
    questions = models.ForeignKey(Question, on_delete=models.CASCADE)
    date_created = models.DateTimeField(auto_now=True, db_index=True)

serializers.py:

class VariantSerializer(serializers.ModelSerializer):
    class Meta:
        model = Variant
        fields = ['id', 'variant']


class QuestionSerializer(serializers.ModelSerializer):
    variants = VariantSerializer(many=True, read_only=True)

    class Meta:
        model = Question
        fields = ['id', 'question', 'multiple', 'variants', 'answer']

    def create(self, validated_data):
        variants_data = validated_data.pop('variants')
        question = Question.objects.create(**validated_data)

        for variant in variants_data:
            Variant.objects.create(question=question, **variant)

        return question


class QuizSerializer(serializers.ModelSerializer):
    questions = QuestionSerializer(many=True)

    class Meta:
        model = Quiz
        fields = ['id', 'name', 'description', 'date_created', 'questions']

    def create(self, validated_data):
        questions_data = validated_data.pop('questions')
        quiz = Quiz.objects.create(**validated_data)

        for question in questions_data:
            Question.objects.create(quiz=quiz, **question)

        return quiz

当我尝试发布一些使用 JSON 文件分配的数据时:

{
    "name": "quiz",
    "description": "quiz quiz quiz",
    "questions": [
        {
            "question": "What is the weather today?",
            "multiple": false,
            "variants": [
                {
                    "variant": "cloudy"
                },
                {
                    "variant": "cold"
                }
            ],
            "answer": "cloudy"
        },
        {
            "question": "What is the weather today?",
            "multiple": false,
            "variants": [
                {
                    "variant": "cloudy"
                },
                {
                    "variant": "cold"
                }
            ],
            "answer": "cloudy"
        }
    ] }

我收到错误 django.db.utils.IntegrityError: NOT NULL constraint failed: api_quiz.questions_id

我是这个框架的新手,我可以做什么来发布数据?

2 个答案:

答案 0 :(得分:0)

您需要更改模型,因为一个 Quiz 只能有一个 Question

class Variant(models.Model):
    variant = models.CharField(max_length=30)

class Question(models.Model):
    question = models.CharField(max_length=250)
    multiple = models.BooleanField(default=False)
    variants = models.ForeignKey(Variant, db_index=True, on_delete=models.CASCADE)
    answer = models.CharField(max_length=30)
    quiz = models.ForeignKey(Question, on_delete=models.DO_NOTHING, related_name="questions") 


class Quiz(models.Model):
    name = models.CharField(max_length=250)
    description = models.TextField()
    date_created = models.DateTimeField(auto_now=True, db_index=True)

我刚刚添加了:

class Question(models.Model):
    quiz = models.ForeignKey(Question, on_delete=models.DO_NOTHING, related_name="questions") 

并删除

class Quiz(models.Model):
    questions = models.ForeignKey(Question, on_delete=models.CASCADE)

所以现在你可以使用:

quiz = Quiz.objects.get(pk=1)
quiz.questions  # Will return all Question 

这在 django 文档中有解释:https://docs.djangoproject.com/en/3.2/topics/db/examples/many_to_one/

注意: 在声明 ForeignKey 使用基于 app.ModelName 的字符串时,最佳做法是永远不要使用模型类,例如您的应用正在调用 quizz_exemple 使用

variants = models.ForeignKey("quizz_exemple.Variant", db_index=True, on_delete=models.CASCADE)

答案 1 :(得分:0)

您必须在Quiz模型中添加Question的外键,因为一个测验可以有很多问题。同样,您必须在 Question 模型中添加 Variant 的外键,因为一个问题可以有多种变体。您还需要添加相关名称,这将有助于编写嵌套 serailizer。此外,您必须按如下方式调整序列化程序:

models.py

class Quiz(models.Model):
    name = models.CharField(max_length=250)
    description = models.TextField()
    date_created = models.DateTimeField(auto_now=True, db_index=True)

class Question(models.Model):
    question = models.CharField(max_length=250)
    multiple = models.BooleanField(default=False)
    answer = models.CharField(max_length=30)
    quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE, related_name='questions')

class Variant(models.Model):
    variant = models.CharField(max_length=30)
    question = models.ForeignKey(Question, db_index=True, on_delete=models.CASCADE, related_name='variants')

serializer.py

class VariantSerializer(serializers.ModelSerializer):
    class Meta:
        model = Variant
        fields = ['id', 'variant']


class QuestionSerializer(serializers.ModelSerializer):
    variants = VariantSerializer(many=True)

    class Meta:
        model = Question
        fields = ['id', 'question', 'multiple', 'variants', 'answer']


class QuizSerializer(serializers.ModelSerializer):
    questions = QuestionSerializer(many=True)

    class Meta:
        model = Quiz
        fields = ['id', 'name', 'description', 'date_created', 'questions']

    def create(self, validated_data):
        questions_data = validated_data.pop('questions')
        quiz = Quiz.objects.create(**validated_data)

        for question in questions_data:
            variants_data = question.pop('variants')
            question_instance = Question.objects.create(quiz=quiz, **question)
            for variant in variants_data:
                Variant.objects.create(question=question_instance, **variant)

        return quiz