How to get the value of the foreign key field and count or other aggregation operations?

Viewed 41

I have two models. How can i count and show results like below:

Male 235

Female 240

Other 10

My models.py

class Student(models.Model):
   name =   models.CharField(max_length = 200)  
   gender =   models.ForeignKey(gender, on_delete = models.SET_NULL, null = True, blank=True)
        
   def __str__(self):
      return '%s' % (self.name)
        
            
class Gender(models.Model):
    title=   models.CharField(max_length = 200)  
  
    def __str__(self):
        return '%s' % (self.title)

My views.py

def viewlist(request):  
    mylist = student.objects.values('gender').annotate(total=Count('gender')).order_by('-total')
1 Answers

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

from django.db.models import Count

gender.objects.annotate(
    nstudents=Count('student')
).order_by('-nstudents')

This will for each gender in the table, annotate the object with the number of students .nstudents. If you thus enumerate over the genders, then for each gender you can retrieve its .nstudents attribute which is the number of related students.

If there is a gender with no related Students, then this gender will still show up in the results, since Django will work with a LEFT OUTER JOIN.

If you pass this to your view, so:

from django.db.models import Count
from django.shortcuts import render

def some_view(request):
    genders = gender.objects.annotate(
        nstudents=Count('student')
    ).order_by('-nstudents')
    return render(request, 'some-template.html', {'genders': genders})</code></pre>

you can render the number of students with:

{% for gender in genders %}
    {{ gender }}: {{ gender.nstudents }}<br>
{% endfor %}

Note: Models in Django are written in PascalCase, not snake_case, so you might want to rename the model from gender to Gender.

Related