Search code examples
djangodjango-templatesdjango-querysetdjango-annotatedjango-aggregation

Username is not showing but user id is showing in html template in Django


Below is my Model :

class Problem_Solved(models.Model):
    user_ref = models.ForeignKey(User, on_delete=models.CASCADE)
    contest_ref = models.ForeignKey(Contest, on_delete=models.CASCADE)
    problem_ref = models.ForeignKey(Problem, on_delete=models.CASCADE)
    points_get = models.IntegerField(default=0)
    time_submitted = models.DateTimeField('date published')
    
    class Meta:
        unique_together = (("user_ref", "problem_ref"))
        

    def __str__(self):
        return self.user_ref.username + " solved " + self.problem_ref.problem_name + " and got " + str(self.points_get) + " marks " 

Below is my view function :

def pointtable(request, contest_id):
    context = {}
    contest_obj=Contest.objects.get(pk=contest_id)
    points_list = Problem_Solved.objects.filter(contest_ref = 
      contest_obj).values('user_ref').annotate(user_sum = Sum('points_get')).order_by('-user_sum')
    print(points_list)
    context['points_list'] = points_list
    return render(request,'leaderboard.html', context)

Now below is my html code :

{% for pt in points_list %}
            <div class="container-sm w-75  tb-bg-color">
                <div class="row mb-3 ">
                    <div class="col-1 themed-grid-col col-border">{{forloop.counter}}</div>
                    <div class="col-6 themed-grid-col col-border">{{pt.user_ref.username}}</div>
                    <div class="col-2 themed-grid-col col-border">{{pt.user_sum}}</div>
                </div>
            </div>
    {% endfor %}

Below is output :

Username is not showing

As clearly seen in image that username is not showing but if I write pt.user_ref in my html code then it will print user_id as shown below :

User id is showing

Now I want username but not user id what should i do as I am stuck with this from 2 days. Help me if u can.


Solution

  • Since you want the points tally of each user annotate on the User model instead, this way you will get a QuerySet of User objects so you can simply get the username:

    def pointtable(request, contest_id):
        context = {}
        contest_obj=Contest.objects.get(pk=contest_id)
        contest_users = User.objects.filter(
            problem_solved__contest_ref = contest_obj
        ).annotate(
            point_sum=Sum('problem_solved__points_get')
        ).order_by('-point_sum')
        context['contest_users'] = contest_users
        return render(request,'leaderboard.html', context)
    

    Now your html would be:

    {% for contest_user in contest_users %}
        <div class="container-sm w-75  tb-bg-color">
            <div class="row mb-3 ">
                <div class="col-1 themed-grid-col col-border">{{forloop.counter}}</div>
                <div class="col-6 themed-grid-col col-border">{{contest_user.username}}</div>
                <div class="col-2 themed-grid-col col-border">{{contest_user.point_sum}}</div>
            </div>
        </div>
    {% endfor %}
    

    Note: Class names should not have underscores in them. So ProblemSolved instead of Problem_Solved