Счетчик количества постов в категории

категория: Django
Смотря в очередной раз на свой блог, мне почему-то очень захотелось около названий категорий выводить количество постов в каждой категории. Естественно я начал писать всякие списки подсчета, потом не знал как вывести эти числа в шаблоне, потом думал, чтоб делать подсчет в базе. А потом ко мне пришло послание свыше в одном слове - "агрегация" (https://docs.djangoproject.com/en/1.4/topics/db/aggregation). Подробнее прочитаете в офф документации. Итак, реализация подсчета постов в категории:
from django.db.models import Count
from blog.models import Category, Post
categories = Category.objects.filter(id__in=range(1,6)).order_by("name")
                              .annotate(count_post = Count('post'))
- у меня категорий 5, поэтому:
.filter(id__in=range(1,6))
- сортировка категорий по имени:
.order_by("name")
- подсчет постов в категории через модель post:
.annotate(count_post = Count('post'))
Вывод ссылок на категории и количеста постов в шаблоне:
{% for category in categories %}
    <a href="{% url categories category.id%}">{{ category.name }}</a>
                                             ({{ category.count_post }})
{% endfor %}
Для себя решил скопировать шпаргалку по агрегациям:
# Total number of books.
>>> Book.objects.count()
2452
# Total number of books with publisher=BaloneyPress
>>> Book.objects.filter(publisher__name='BaloneyPress').count()
73
# Average price across all books.
>>> from django.db.models import Avg
>>> Book.objects.all().aggregate(Avg('price'))
{'price__avg': 34.35}
# Max price across all books.
>>> from django.db.models import Max
>>> Book.objects.all().aggregate(Max('price'))
{'price__max': Decimal('81.20')}
# Each publisher, each with a count of books as a "num_books" attribute.
>>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count('book'))
>>> pubs
[, , ...]
>>> pubs[0].num_books
73
# The top 5 publishers, in order by number of books.
>>> from django.db.models import Count
>>> pubs = Publisher.objects.annotate(num_books=Count('book')).order_by('-num_books')[:5]
>>> pubs[0].num_books
1323


blog comments powered by Disqus