Reputation: 200
I have a quiz model and a view where I'm displaying a list of all the quizzes on the page. I want to show the score that they got alongside each quiz. Currently, I have a score model that links to each quiz and the user that took the quiz. I want to do something like Score.objects.filter(user=request.user, quiz=quiz).get_percentage()
to show the percentage achieved for that quiz. However this doesn't work in template code of course.
def learn(request): #Quiz Screen
context = {
'quizzes':Quiz.objects.all(),
'scores':Score.objects.filter(user=request.user),
}
return render(request, 'quiz_app/learn.html', context)
{% extends "quiz_app/base.html" %}
{% block content %}
<a href="{% url 'quiz-create' %}">New Quiz</a>
{% for quiz in quizzes %}
<a id="quiz-anchor" href="{% url 'quiz-detail' quiz.id %}">
<article class="quiz-thumbnail-large">
<h2>{{ quiz.title }}</h2>
<h3>{{ quiz.question_amount }} Questions</h3>
<p>Score: {{ quiz.score.get_percentage }}%</p>
</article>
</a>
{% endfor %}
{% endblock content %}
class Quiz(models.Model):
title = models.CharField(max_length=100) #or TextField
#slug = models.SlugField(max_length=200, default=1) #url
video_link = models.CharField(max_length=100, default="https://www.youtube.com/watch?v=p60rN9JEapg")
question_amount = models.IntegerField()
author = models.ForeignKey(User, default=1, on_delete=models.CASCADE, related_name='quiz_author',)
date_created = models.DateTimeField(default=timezone.now)
class Meta:
verbose_name_plural = "Quizzes"
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('quiz-detail', kwargs={'pk': self.pk})
class Score(models.Model):
quiz = models.ForeignKey(Quiz, default=1, on_delete=models.CASCADE)
user = models.ForeignKey(User, default=1, on_delete=models.CASCADE)
correct_answers = models.IntegerField()
incorrect_answers = models.IntegerField()
def __str__(self): #returns as a/b
score = str(self.correct_answers) + '/' + str(self.get_total_answers())
return score
def add_correct_answers(self, amount):
self.correct_answers = self.correct_answers + amount
self.save()
def add_incorrect_answers(self, amount):
self.incorrect_answers = self.incorrect_answers + amount
self.save()
def get_total_answers(self):
total = self.correct_answers + self.incorrect_answers
return total
def get_percentage(self):
percentage = round(self.correct_answers / self.get_total_answers() * 100)
return percentage
Upvotes: 0
Views: 141
Reputation: 3920
So as you have a foreign Key relationship between Quiz
and Score
, you can have multiple scores for a single quiz, therefore you should use the backward relationship from the quiz
model like this:
{% extends "quiz_app/base.html" %}
{% block content %}
<a href="{% url 'quiz-create' %}">New Quiz</a>
{% for quiz in quizzes %}
<a id="quiz-anchor" href="{% url 'quiz-detail' quiz.id %}">
<article class="quiz-thumbnail-large">
<h2>{{ quiz.title }}</h2>
<h3>{{ quiz.question_amount }} Questions</h3>
{% for score in quiz.score_set.all %}
<p>Score: {{ score.get_percentage }}%</p>
{% endfor %}
</article>
</a>
{% endfor %}
{% endblock content %}
This is a quick fix:
{% extends "quiz_app/base.html" %}
{% block content %}
<a href="{% url 'quiz-create' %}">New Quiz</a>
{% for quiz in quizzes %}
<a id="quiz-anchor" href="{% url 'quiz-detail' quiz.id %}">
<article class="quiz-thumbnail-large">
<h2>{{ quiz.title }}</h2>
<h3>{{ quiz.question_amount }} Questions</h3>
{% for score in quiz.score_set.all %}
{% if score.user == request.user %}
<p>Score: {{ score.get_percentage }}%</p>
{% endif %}
{% endfor %}
</article>
</a>
{% endfor %}
{% endblock content %}
But it's not a good idea, because you will retrieve all the score for all the users first, and then filter them; It's better to use a template tag here.
Upvotes: 2