I've got a simple Model like this:
class Order(models.Model):
created = model.DateTimeField(auto_now_add=True)
total = models.IntegerField() # monetary value
And I want to output a month-by-month breakdown of:
- How many sales there were in a month (
COUNT
) - The combined value (
SUM
)
I'm not sure what the best way to attack this is. I've seen some fairly scary-looking extra-select queries but my simple mind is telling me I might be better off just iterating numbers, starting from an arbitrary start year/month and counting up until I reach the current month, throwing out simple queries filtering for that month. More database work - less developer stress!
What makes most sense to you? Is there a nice way I can pull back a quick table of data? Or is my dirty method probably the best idea?
I'm using Django 1.3. Not sure if they've added a nicer way to GROUP_BY
recently.
Another approach is to use
ExtractMonth
. I ran into trouble using TruncMonth due to only one datetime year value being returned. For example, only the months in 2009 were being returned. ExtractMonth fixed this problem perfectly and can be used like below:By month:
By Year:
By day:
Don't forget to import Count
For django < 1.10
Just a small addition to @tback answer: It didn't work for me with Django 1.10.6 and postgres. I added order_by() at the end to fix it.
Here's my dirty method. It is dirty.
There may well be a better way of looping years/months but that's not really what I care about :)
Django 1.10 and above
Django documentation lists
extra
as deprecated soon. (Thanks for pointing that out @seddonym, @Lucas03). I opened a ticket and this is the solution that jarshwah provided.Older versions
Edits