tags:

views:

82

answers:

2

My models look something like this:

class Customer(models.Model):
   name = models.CharField(max_length=100)

class Order(models.Model):
   customer = models.ForeignKey(Customer)
   date = models.DateField()
   total = models.DecimalField(max_digits=5, decimal_places=2)

I then have a queryset of orders:

from datetime import datetime

start_date = datetime(year=2009, month=6, day=1)
end_date = datetime(year=2009, month=11, day=1)
orders = Order.objects.filter(date__lte=end_date).filter(date__gte=start_date)

Now, I want to find out which customers made multiple orders between those times, how many orders they made, and what their average total is. I get the feeling that I should be using Django 1.1's new aggregation features, but I can't really wrap my head around it.

A: 

This would be a good use for Django 1.1's annotate() functionality, which is part of aggregateion. Specifically, you'll probably want to use the values() function.

Soviut
right, so for the average order total, I'd do a query like Order.objects.values('customer').annotate(avg_total=Avg('total')), but how do I get the number of orders each customer has?
Udbhav
you can use `.count()` to get a count of the filtered queries.
thornomad
+1  A: 

Always base your query around the object in which you are primarily interested in:

repeat_customers = Customer.objects.annotate(order_count=Count('order'))\
                                   .filter(order_count__gt=1)

Then if you want to annotate with their totals (you could alternatively do this in the annotation above, I'm just separating the code for readability):

repeat_customers = repeat_customers.annotate(avg_total=Avg('order__total'))
SmileyChris
thanks, that makes sense to me. Now how would I restrict the orders annotated to only orders within my orders queryset?
Udbhav
Just string your filters together:Customer.objects.annotate(order_count=Count('order')).filter(order_count__gt=1, date__lte=end_date, date__gte=start_date)
Jack M.