Django Queryset help, count items associated with item

Viewed 315

I am making a web application for an inventory management application using Django. In this web app, storage boxes (with contents) are assigned to people in my database.

I am trying to write a queryset that I could loop over (see my HTML) that would retrieve the total number of boxes assigned to each project e.g. Project: Project Green, Total Boxes: 5. Im having difficulty writing this. I've tried to use _Set for a reverse lookup and the count function but I can't get anything to work.

Could somebody point me in the right direction?

I've simplified my code below.

My model:

class Box(models.Model):
    box_contents = models.CharField(max_length=300, blank=True, null=True) 
    project_assigned_to = models.ForeignKey('Project', null=True)
    Location = models.OneToOneField('Location', null=True)

class Project(models.Model):
    project_name = models.CharField(max_length=255, blank=False, null=True)

My View:

def page(request):
    project_data = Project.objects.all()
    return render(request, 'main_app/page.html' , 
    {"project_data":project_data})

My HTML:

{% for item in project_data %}
<p>Project Name: {{ item.project_name }}</p>
<p>Number of Boxes Assigned: {{ item.Box_set.box_contents.count }}</p>
{% endfor %}
1 Answers

You can count the number of Boxes associated with a Project with:

{{ item.box_set.count }}

But this will result in the famous N+1 problem: you will make an extra query per item. You can avoid this by annotating the queryset first with the number of Boxes, like:

from django.db.models import Count

def page(request):
    project_data = Project.objects.annotate(
        nboxes=Count('box')
    )
    return render(request, 'main_app/page.html' , 
    {"project_data":project_data})

Now the Projects in this QuerySet will have an extra attribute named nboxes, so then you can render this with:

{% for item in project_data %}
<p>Project Name: {{ item.project_name }}</p>
<p>Number of Boxes Assigned: {{ item.nboxes }}</p>
{% endfor %}
Related