首页 > 解决方案 > Django REST框架:在序列化程序中获取相关模型的字段

问题描述

我是 Django Rest 框架的新手。我试图让我ListAPI展示我Quiz(和相关)模型的各个领域。它工作正常,除了我的attempt_number领域。我得到了正确的查询集,但我不确定如何只获取每个查询的相关值。用户可以根据需要多次参加每个测验,我想显示每次尝试的查询集,因为分数等会有所不同。

我的模型设置如下:

class Quiz(models.Model):
    title = models.CharField(max_length=15)
    slug = models.SlugField(blank=True)
    questions_count = models.IntegerField(default=0)

class Question(models.Model):
    quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
    label = models.CharField(max_length=1000)

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    answer = models.CharField(max_length=100)
    is_correct = models.BooleanField('Correct answer', default=False)

class QuizTaker(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    quiz = models.ForeignKey(Quiz, on_delete=models.CASCADE)
    correct_answers = models.IntegerField(default=0)
    completed = models.BooleanField(default=False)
    attempt_number = models.PositiveIntegerField(default=0)

我的序列化器ListAPI看起来如下:

class MyQuizListSerializer(serializers.ModelSerializer):
    attempt = serializers.SerializerMethodField()
    # etc..
    class Meta:
        model = Quiz
        fields = "__all__"

    def get_attempt(self, obj):
        try:
            quiztaker = QuizTaker.objects.filter(user=self.context['request'].user,
                quiz=obj)
            for attempt in quiztaker:
                attempt_number = attempt.attempt_number
            return attempt_number

如果我这样做,我总是会得到最后一个值attempt_number(因为循环会覆盖该值)。因此,我尝试将其附加到列表中,如下所示:

a = []
for attempt in quiztaker:
    attempt_number = attempt.attempt_number
    a.append(attempt_number)
return a

但是后来我得到了每个查询的尝试列表,而不是每个查询的尝试次数。即我得到以下三次(因为在这种情况下有三次尝试):

{
    "id": 4,
    "attempt": [
        1,
        2,
        3
    ]
},

但相反,我想要的是(对于尝试 2 和 3 等也是如此):

{
    "id": 4,
    "attempt": 1
},

所以我试着这样做:

return a[attempt_number-1]

希望它会给我第 1 次尝试的索引零,第 2 次的索引为 1,等等。但是我仍然只是得到最后一次尝试编号(在这种情况下为 3)。我该如何解决这个问题?

我也尝试使用 aIntegerField而不是 aSerializerMethodField如下:

attempt = serializers.IntegerField(read_only=True, source='quiztaker.attempt_number')

但它什么也没返回。

标签: pythondjangodjango-modelsserializationdjango-rest-framework

解决方案


如果我正确理解您,您希望将尝试列表添加到每个测验对象。

{
    "id": 4,
    "attempts": [{
        "id": 1,
        "attempt_number": 1,
    },
    {
        "id": 2,
        "attempt_number": 2,
    }...]
}

在这种情况下,您应该有一个单独的QuizTaker模型序列化程序并序列化SerializerMethodField.

class QuizTakerSerializer(serializers.ModelSerializer):
    class Meta:
        model = QuizTaker
        fields = ('id', 'attempt_number')
 
class MyQuizListSerializer(serializers.ModelSerializer):
    attempts = serializers.SerializerMethodField()
    # etc..
    class Meta:
        model = Quiz
        fields = "__all__"

    def get_attempts(self, obj):
        quiztakers = QuizTaker.objects.filter(user=self.context['request'].user,quiz=obj)
        return QuizTakerSerializer(quiztakers, many=True).data

老实说,您的问题不是很清楚,这将有助于对其进行编辑并使其更清晰,从而提供您想要实现的 JSON 结构。我还怀疑您打算使用的queryset不是ORM 对象容器的实际 Django 含义。


推荐阅读