Reputation: 1269
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.
Upvotes: 6
Views: 10998
Reputation: 6296
If I correctly understood you, you want the list of attempts added to each quiz object.
{
"id": 4,
"attempts": [{
"id": 1,
"attempt_number": 1,
},
{
"id": 2,
"attempt_number": 2,
}...]
}
In that case, you should have a separate serializer for the QuizTaker
model and serialize the objects in the 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
Honestly, your question is not very clear and it would help to edit it and make it clearer, giving the JSON structure you want to achieve. I also suspect your intended use of queryset
isn't the actual Django meaning for a container of ORM objects.
Upvotes: 6