Theofanis Despoudis started out as a PHP
(Pretty Horrible Pages) developer at first. He’s a recent python enthousiast.

Aggregations are basically database functions. Django abstracts away the
details behind a simple function. It is useful for producing summaries over
collections of objects. Stuff like average, maximum, minimum, sum, count,
standard deviation, variance. There is probably more on the database level,
but this is the list that django supports.

He showed a couple of examples like
Gamer.objects.all().aggregate(num_wins=Count('won')). It translates to a
quite well optimized SQL query. With django, you don’t have to do this by
hand.

Annotations is a second way to generate summary values. The difference is
that it doesn’t aggregate all the objects, but that it adds the summary
value to every individual result. So instead of the total number of games won
like in the aggregate example, you can now add an extra ‘column’ to every
individual result like this:
Gamer.objects.all().annotate(num_wins=Count('won'))

Nice: you can also slice and order on annotations. You can order the above
results by num_wins and pick the highest 5:
Gamer.objects.all().annotate(num_wins=Count('won')).order_by('num_wins')[:5]

You can also combine annotations with automatic grouping by calling
.values(). With
Gamer.objects.values('region').annotate(num_wins=Count('won')) you’d get a
list of dicts with regions and the number of wins. [{'region':'eu','num_wins':4},...].

Practical tips:

You can collect your aggregated queries in a separate object manager.

You can aggregate and annotate and group a lot with the django ORM, but
you have to keep in mind what you really need. And what you really
originally wanted to query.