Personal Catalogue: Django & PostgreSQL — Chapter 6, Exercise 3 ==================================================== TASK Build the TagIndexView and its template, and explain in your own words why Count('items') is a meaningfully faster approach than looping over every tag and calling tag.items.count() individually. SOLUTION 1. catalogue/views.py: from django.db.models import Count from .models import Tag class TagIndexView(ListView): model = Tag template_name = 'catalogue/tag_index.html' context_object_name = 'tags' queryset = Tag.objects.annotate(item_count=Count('items')).order_by('-item_count') 2. catalogue/urls.py: path('tags/', views.TagIndexView.as_view(), name='tag_index'), 3. catalogue/templates/catalogue/tag_index.html: {% extends 'catalogue/base.html' %} {% block content %} {% endblock %} WHY Count('items') IS MEANINGFULLY FASTER THAN A LOOP The alternative approach - fetching all Tag rows, then looping over each one and calling tag.items.count() - issues one initial query to fetch the tags, and then one SEPARATE query per tag to count its related items. For N tags, that's N+1 total queries, the exact same kind of query-count problem the site's own N+1 finding in Chapter 4 already covered for tags on the item list page - just occurring here on the tag side of the relationship instead of the item side. Count('items'), used with annotate(), instead produces a single SQL query that joins Tag against Item (via the auto-generated join table) and groups the results by tag, computing every tag's own item count in that one query. Whether there are 5 tags or 500, the query count stays exactly 1 - the database itself does the counting and grouping work in one pass, rather than the application issuing a separate round-trip per tag. ANSWER: Count('items') combined with annotate() computes every tag's own item total in a single database query, using a real SQL JOIN and GROUP BY under the hood. Looping over each tag and calling tag.items.count() individually issues one additional query per tag on top of the initial tag-fetching query - an N+1 query pattern that gets measurably slower as the number of tags grows, exactly the same class of problem the site's own item-list N+1 bug represented, just occurring on the opposite side of the same tags relationship. WHY THIS WORKS AS AN ANSWER ---------------------------- It builds the real view/template pair, and explains the performance difference in terms of actual query counts rather than a vague "it's more efficient" claim, explicitly connecting it back to the N+1 pattern already established earlier in the course.