Group results with multiple uses of annotate()

26 views
Skip to first unread message

Adam Starrh

unread,
Sep 8, 2016, 2:04:40 PM9/8/16
to Django users
I've got the following function in a manager which seems to work well, annotating data and grouping results by "variety name":



def by_variety_and_date(self, start_date, end_date):
   
return self.model.objects.filter(
        date__range
=(start_date, end_date)
   
).values(
       
"variety__name"
   
).annotate(
        total_kgs
=Sum('qty_applied'),
        total_profit
=Sum('profit'),
        grand_total_cogs
=Sum('total_cogs'),
        total_sales
=Sum('value'),
   
).order_by('-total_kgs')



However, I would like to add a piece of information like so:


def by_variety_and_date(self, start_date, end_date):
   
return self.model.objects.filter(
        date__range
=(start_date, end_date)
   
).values(
       
"variety__name"
   
).annotate(
        total_kgs
=Sum('qty_applied'),
        total_profit
=Sum('profit'),
        grand_total_cogs
=Sum('total_cogs'),
        total_sales
=Sum('value'),
   
).annotate(
        final_margin
=Case(
       
When(total_sales=0, then=0),
       
default=(Sum(F('profit')) / Sum(F('value')))*100
       
)
   
).order_by('-total_kgs')

In this case, the grouping doesn't work, and each item is returned separately. Essentially `.values().annotate()` works, but `.values().annotate().annotate()` seems to break. 

I've also tried `.annotate().annotate().values()` as well to no avail.

Is this the intended behavior? Am I missing a piece of instruction? 

Adam Starrh

unread,
Sep 8, 2016, 4:15:26 PM9/8/16
to Django users
OK I got this to work. The second annotate needs to go at the end, so that the order is as follows: .filter().values().annotate().order_by().annotate()
Reply all
Reply to author
Forward
0 new messages