Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between Django's annotate and aggregate methods?

People also ask

What is the difference between aggregate and annotate?

Aggregate calculates values for the entire queryset. Annotate calculates summary values for each item in the queryset.

What is annotate () in Django?

Appending the annotate() clause onto a QuerySet lets you add an attribute to each item in the QuerySet, like if you wanted to count the amount of articles in each category. However, sometimes you only want to count objects that match a certain condition, for example only counting articles that are published.

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.


I would focus on the example queries rather than your quote from the documentation. Aggregate calculates values for the entire queryset. Annotate calculates summary values for each item in the queryset.

Aggregation

>>> Book.objects.aggregate(average_price=Avg('price'))
{'average_price': 34.35}

Returns a dictionary containing the average price of all books in the queryset.

Annotation

>>> q = Book.objects.annotate(num_authors=Count('authors'))
>>> q[0].num_authors
2
>>> q[1].num_authors
1

q is the queryset of books, but each book has been annotated with the number of authors.


Aggregate Aggregate generate result (summary) values over an entire QuerySet. Aggregate operate over the rowset to get a single value from the rowset.(For example sum of all prices in the rowset). Aggregate is applied on entire QuerySet and it generate result (summary) values over an entire QuerySet.

In Model:

class Books(models.Model):
    name = models.CharField(max_length=100)
    pages = models.IntegerField()
    price = models.DecimalField(max_digits=5, decimal_places=3)

In Shell:

>>> Books.objects.all().aggregate(Avg('price'))
# Above code will give the Average of the price Column 
>>> {'price__avg': 34.35}

Annotate Annotate generate an independent summary for each object in a QuerySet.(We can say it iterate each object in a QuerySet and apply operation)

In Model:

class Video(models.Model):
    name = models.CharField(max_length=52, verbose_name='Name')
    video = models.FileField(upload_to=document_path, verbose_name='Upload 
               video')
    created_by = models.ForeignKey(User, verbose_name='Created by', 
                       related_name="create_%(class)s")
    user_likes = models.ManyToManyField(UserProfile, null=True, 
                  blank=True, help_text='User can like once', 
                         verbose_name='Like by')

In View:

videos = Video.objects.values('id', 'name','video').annotate(Count('user_likes',distinct=True)

In view it will count the likes for each video


That's the main difference, but aggregates also work on a grander scale than annotations. Annotations are inherently related to individual items in a queryset. If you run an Count annotation on a something like a many-to-many field, you'll get a separate count for each member of the queryset (as an added attribute). If you were to do the same with an aggregation, however, it would attempt to count every relationship on every member of the queryset, even duplicates, and return that as just one value.