user16625329
user16625329

Reputation:

Displaying data in a leaderboard - Django

I have the following model:

class UserDetail(models.Model):
  donations = models.IntegerField(blank=True, null = True,)
  points = models.IntegerField(blank=True, null = True,)
  requests = models.IntegerField(blank=True, null=True)
  user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE,
        blank=True,
        null=True,
    )

I want to get the top 5 users with the most points and display them in an HTML leaderboard template.

Please help

EDIT:

MY VIEW:

def leaderboard(request,):
    User.objects.alias(
    total_points=Sum('userdetail__points')
    ).order_by('-total_points')[:5]

    return render(request, 'leaderboard.html')

Upvotes: 1

Views: 686

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476699

You can work with a .annotate(…) [Django-doc] and then .order_by(…) [Django-doc]:

from django.db.models import Sum

User.objects.annotate(
    total_points=Sum('userdetail__points')
).order_by('-total_points')[:5]

Since you can work with .alias(…) [Django-doc] to prevent calculating this both as column and in the ORDER BY clause:

from django.db.models import Sum

User.objects.alias(
    total_points=Sum('userdetail__points')
).order_by('-total_points')[:5]

Regardless which of the two you pick, you pass these to the context in the template:

def leaderboard(request,):
    leaders = User.objects.alias(
        total_points=Sum('userdetail__points')
    ).order_by('-total_points')[:5]

    return render(request, 'leaderboard.html', {'leaders': leaders})

and in the template you can render the leaderbord with:

{% for leader in leaders %}
    {{ leader.username }}
{% endfor %}}

If you want to add the points next to the username, you should work with the .annotate(…) variant. You can then render this with:

<table>
  <th><td>User</td><td>Points</td></th>
{% for leader in leaders %}
    <tr><td>{{ leader.username }}</td><td>{{ leader.total_points }}</td></tr>
{% endfor %}
</table>

Upvotes: 2

Related Questions