Django: GROUP BY datetime

While trying to make the archive pages of this site more useful, I had a bit of trouble working with Django's annotation feature to give me the numbers I was looking for. I wanted to show on the index page how many posts were published in a given month. This ticket was very helpful to figure out how to do it, and as a bonus it means it will work more simply in future-Django :)

At the moment, the workaround is unfortunately database specific. The ticket contains an example using SQLite, here's how I did it using PostgreSQL. I think with MySQL you'd need to play with YEAR() and MONTH() to get the same.

bymonth_select = {"month": """DATE_TRUNC('month', creation_date)"""} # Postgres specific
months = Article.objects.exclude(draft=True).extra(select=bymonth_select).values('month').annotate(num_posts=Count('id')).order_by('-month')

I removed a couple of filters for readability, but this is basically a normal QuerySet with a couple of Django caveats:

  1. Write your filters before the annotate call, as the Count() processes only what comes before it
  2. .values('blah') for a GROUP BY effect, without it you'll get '1' for every record fetched back
  3. .order_by(), with or without an argument otherwise things will likely get messed up by the order_by of your Meta class if any -- inspired by comment #8 of the ticket linked above, thanks!

< Back to main >

No comments yet.

Hello! This text is normally hidden with CSS. If you can see this, you'll also see two additional fields with no label on the form. Leave them as is, as those are aimed at catching form-filling spam bots. Thank you!

    Name: (or OpenID Sign in with OpenID)
      Email: (Not published)
        Website:
          Comment:
           

          < Back to main | Up >