Django annotate groupings by month

后端 未结 4 1086
猫巷女王i
猫巷女王i 2020-12-08 06:13

I have a very basic model:

class Link(models.Model):
    title = models.CharField(max_length=250, null=False)
    user = models.ForeignKey(User)
    url = mo         


        
相关标签:
4条回答
  • 2020-12-08 06:14
    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'))
    
    0 讨论(0)
  • 2020-12-08 06:27

    I've read that .extra() will be deprecated in the future. They are suggesting to instead use Func objects. And there is one for extracting a month without using a painful Case statement.

    from django.db.models.functions import ExtractMonth
    Link.objects.all().annotate(pub_date_month=ExtractMonth('pub_date'))
    
    0 讨论(0)
  • 2020-12-08 06:33

    To add, as an alternative for using extra(): since Django 1.8, you can also use conditional expressions.

    >>> 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}
    
    0 讨论(0)
  • 2020-12-08 06:38

    If you're on PostgreSQL, the following might work:

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

    I'm not sure how portable extract is across other databases.

    0 讨论(0)
提交回复
热议问题