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.
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.
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.
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.
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.
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
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'))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With