#StackBounty: #python #django #django-models #serialization #django-rest-framework Django REST framework: get field of related model in…

Bounty: 50

I’m new to Django Rest Framework. I’m trying to get my ListAPI to show various fields of my Quiz (and related) models. It’s working fine, except for my attempt_number field. I’m getting the right queryset, but I’m not sure how to get only the relevant value for every query. Users can take every quiz as many times as they want, and I want to show the queryset for each attempt, since the score etc. will be different.

My model setup is as follows:

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)

My serializer for the ListAPI looks as follows:

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

If I do it like this, I always get the last value for attempt_number (because the loop overwrites the value). So then I tried to append it to a list instead, like this:

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

But then I get the list of attempts for every query, instead of the attempt number for each query. I.e. I get the following three times (because in this case there are three attempts):

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

But instead what I want is (and the same for attempt 2 and 3 etc.):

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

So I tried doing it like this:

return a[attempt_number-1]

Hoping it would give me index zero for attempt number 1, 1 for 2, etc. But then I still just get the last attempt number (3 in this case). How can I solve this?

I also tried just using an IntegerField instead of a SerializerMethodField as follows:

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

But it returned nothing.


Get this bounty!!!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.