×
annotate
Returns a QuerySet with the annotated fields added.
Each object in the queryset will have the extra field as an attribute.
Often used with aggregation functions from django.db.models, like Count, Sum, Avg, Max, Min.
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
author = models.ForeignKey(Author, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
authors = Author.objects.annotate(num_books=Count('book'))
for author in authors:
print(author.name, author.num_books)
___
actor = Actor.objects.prefetch_related('starring_movies')
.annotate(avg_r=Avg('starring_movies__rating'), stars=Count('starring_movies'))
.order_by('-stars', 'full_name').first()
annotate(avg_r=Avg(...), stars=Count(...))
Adds per-actor fields:
avg_r → average rating of that actor’s movies
stars → number of movies that actor starred in
These are calculated individually for each actor.
Why .aggregate() is different
Actor.objects.aggregate(avg_r=Avg('starring_movies__rating'))
Computes one single value for the entire queryset.
Returns a dictionary: {'avg_r': 7.5}
You cannot chain .annotate() or .order_by() after it, because it’s no longer a queryset — it’s a single summary.
annotate() - Per object / per row - QuerySet of objects with extra fields - Average rating of each actor’s movies
aggregate() - Whole queryset - Single dict - Average rating across all actors’ movies