Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django aggregate or annotate

This is a very stupid thing, I know, but I just don't seem to get the handle on Django aggregate and annotate functions.

I have a very simple set of models: Events, Areas and Types. An event has foreign keys pointing to Area and Type. I would simply like to have the number of forthcoming events for any area and the same for any type, i.e. Area1 - 5 forthcoming events, Area2 - 6, or Type1 - 34 events and so on.

I would like to avoid writing custom SQL, and the q operator if possible.

like image 957
freethrow Avatar asked Jan 05 '12 13:01

freethrow


People also ask

What is difference between annotate and aggregate in Django?

Difference between annotate() and aggregate(): annotate() aims to evaluate every row in a queryset and create a pseudo field for the same, whereas aggregate() evaluates the queryset as a whole and brings out the final result.

Why we use annotate in Django?

In the Django framework, both annotate and aggregate are responsible for identifying a given value set summary. Among these, annotate identifies the summary from each of the items in the queryset. Whereas in the case of aggregate, the summary is calculated for the entire queryset.

What does aggregate do in Django?

When specifying the field to be aggregated in an aggregate function, Django will allow you to use the same double underscore notation that is used when referring to related fields in filters. Django will then handle any table joins that are required to retrieve and aggregate the related value.

What is annotate function in Django?

Annotation is a computation that is done on a database level. Django provides you only a set of basic computations which can be processed by the database - SUM, AVERAGE, MIN, MAX and so on... For more complex stuffs only from version 1.8 we have an API for more complex query expressions.


2 Answers

for a given area:

my_area = Area.objects.all()[0]
Event.objects.filter(area=my_area).count()

annotation

events = Event.objects.annotate(Count('area'))
for event in events:
    print event, event.area__count

or

events = Event.objects.annotate(count=Count('area'))
for event in events:
    print event, event.count

See the following docs:

https://docs.djangoproject.com/en/dev/ref/models/querysets/#annotate

like image 72
c4urself Avatar answered Oct 12 '22 14:10

c4urself


If you just need the total number of events for a single area, you don't need either annotate or aggregate, a simple count will do:

Event.objects.filter(area=my_area).count()

If you want the count of events for multiple areas, you need annotate in conjunction with values:

Event.objects.values('area').annotate(Count('area'))
like image 29
Daniel Roseman Avatar answered Oct 12 '22 14:10

Daniel Roseman