I've a StudentAnswer model which stores the answer id given by the student(User) in a quiz. If the answer is correct then 1 marks else 0. The model looks like this:
class StudentAnswer(models.Model):
user = models.ForeignKey(User, related_name='user_question_answer',
on_delete=models.SET_NULL,null=True, blank=True)
answer = models.ForeignKey(QuizQuestionAnswer, related_name='user_answer',
on_delete=models.CASCADE)
quiz = models.ForeingKey(Quiz, on_delete=models.CASCADE)
marks = models.IntegerField()
Now I need my response to look something like this: { "rank": 1, "user": "John Doe", "marks": 10 }, { "rank": 2, "user": "Stanley", "marks": 8 }
I don't have a rank field in my model. I want rank in my response and that too according to the marks of students(highest to lowest). How can I do it?
CodePudding user response:
The absolutely easiest way to do this is to use order_by('marks')
and then in your view or template, when you are looping through each User, their rank is just the index of the loop. Two examples:
# template
{% for student in students %}
# rank is {{ forloop0.counter }}
{% endfor %}
# views
for index, value in enumerate(students):
# rank is index
...
If you want to explicitly add the rank to the queryset then you can use annotation, see the answer to this question: Django model - how to add order index annotation?
from django.db.models import Window, F
from django.db.models.functions import DenseRank
ranklist = Score.objects.annotate(
place=Window(
expression=DenseRank(),
order_by=[
F('points').desc(),
]))