Джанго аннотирует группировки по месяцам - PullRequest
16 голосов
/ 23 августа 2010

У меня есть очень базовая модель:

class Link(models.Model):
    title = models.CharField(max_length=250, null=False)
    user = models.ForeignKey(User)
    url = models.CharField(max_length=250, blank=True, null=True)
    link_count = models.IntegerField(default=0)
    pub_date = models.DateField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)

Я могу создать список всех записей, сгруппированных по дате, используя:

Link.objects.values('pub_date').order_by('-pub_date').annotate(dcount=Count('pub_date'))

Это естественно группирует предметы по дням. Но то, что я действительно хочу сделать, это группировать по месяцам. Есть ли в любом случае я могу сделать это с помощью annotate ()?

Большое спасибо,

G

Ответы [ 4 ]

15 голосов
/ 23 августа 2010

Если вы используете PostgreSQL, может работать следующее:

from django.db.models import Count

Link.objects.extra(select={'month': 'extract( month from pub_date )'}).values('month').annotate(dcount=Count('pub_date'))

Я не уверен, насколько портативен extract для других баз данных.

13 голосов
/ 04 ноября 2010
from django.db import connections
from django.db.models import Count

Link.objects.extra(select={'month': connections[Link.objects.db].ops.date_trunc_sql('month', 'pub_date')}).values('month').annotate(dcount=Count('pub_date'))
3 голосов
/ 10 ноября 2016

Я читал, что .extra() устареет в будущем. Вместо этого они предлагают использовать Func объекты. И есть один для извлечения месяца без использования болезненного Case заявления.

from django.db.models.functions import ExtractMonth
Link.objects.all().annotate(pub_date_month=ExtractMonth('pub_date'))
3 голосов
/ 21 апреля 2016

Чтобы добавить, в качестве альтернативы для использования extra(): начиная с Django 1.8, вы также можете использовать условные выражения.

>>> year_overview = Link.objects.filter(pub_date__year=year).aggregate(
    jan=Sum(
        Case(When(created__month=0, then=1),
             output_field=IntegerField())
    ),
    feb=Sum(
        Case(When(created__month=1, then=1),
             output_field=IntegerField())
    ),
    mar=Sum(
        Case(When(created__month=2, then=1),
             output_field=IntegerField())
    ),
    apr=Sum(
        Case(When(created__month=3, then=1),
             output_field=IntegerField())
    ),
    may=Sum(
        Case(When(created__month=4, then=1),
             output_field=IntegerField())
    ),
    jun=Sum(
        Case(When(created__month=5, then=1),
             output_field=IntegerField())
    ),
    jul=Sum(
        Case(When(created__month=6, then=1),
             output_field=IntegerField())
    ),
    aug=Sum(
        Case(When(created__month=7, then=1),
             output_field=IntegerField())
    ),
    sep=Sum(
        Case(When(created__month=8, then=1),
             output_field=IntegerField())
    ),
    oct=Sum(
        Case(When(created__month=9, then=1),
             output_field=IntegerField())
    ),
    nov=Sum(
        Case(When(created__month=10, then=1),
             output_field=IntegerField())
    ),
    dec=Sum(
        Case(When(created__month=11, then=1),
             output_field=IntegerField())
    ),
)

>>> year_overview
{'mar': None, 'feb': None, 'aug': None, 'sep': 95, 'apr': 1, 'jun': None, 'jul': None, 'jan': None, 'may': None, 'nov': 87, 'dec': 94, 'oct': 100}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...