Django Aggregate vs Annotate with example

Mehedi Khan
2 min readJul 27, 2024

--

Django Aggregate vs Annotate with example

Django’s aggregate and annotate functions are used to perform calculations on querysets. While they might seem like similar, they serve different purposes. Here’s a tutorial with examples to illustrate their use.

Aggregate

The aggregate function is used to perform a calculation on a queryset and return a dictionary of the computed values. It is generally used for overall summary operations.

Example:

Suppose you have a model called Order:

# models.py

from django.db import models


class Order(models.Model):
customer = models.CharField(max_length=100)
amount = models.DecimalField(max_digits=10, decimal_places=2)
date = models.DateField()

You can use aggregate to get the total amount of all orders:

# views.py or shell

from django.db.models import Sum
from .models import Order

total_amount = Order.objects.aggregate(Sum('amount'))
print(total_amount) # {'amount__sum': Decimal('Total Amount')}

This will be return dictionary with key amount__sum containing the sum of all amount fields in the Order model.

Annotate

The annotate function is used to calculate values for each item in a queryset. This is typically used for per-item calculations rather than overall summaries.

Example:

Continuing with the Order model, suppose you have another model called Customer:

# models.py

from django.db import models


class Customer(models.Model):
name = models.CharField(max_length=100)

To get the total amount of orders per customer, you can use annotate:

# views.py or shell

from django.db.models import Sum
from .models import Customer, Order


customers_with_order_totals = Customer.objects.annotate(total_amount=Sum('order__amount'))
for customer in customers_with_order_totals:
print(customer.name, customer.total_amount)

This will add a total_amount attribute to each Customer instance, containing the sum of the amount of all their orders.

Comparison

Aggregate: Used for overall summaries.

  • Returns a single dictionary with calculated values.
  • Example: Order.objects.aggregate(Sum('amount'))

Annotate: Used for per-item calculations.

  • Returns a queryset where each item has the calculated values as additional attributes.
  • Example: Customer.objects.annotate(total_amount=Sum('order__amount'))

Practical Example

Consider a model Product and Sales:

# models.py

from django.db import models


class Product(models.Model):
name = models.CharField(max_length=100)


class Sales(models.Model):
product = models.ForeignKey(Product, on_delete=models.CASCADE)
quantity = models.IntegerField()
date = models.DateField()

Aggregate Example: Total Sales Quantity

# views.py or shell

from django.db.models import Sum
from .models import Sales


total_sales_quantity = Sales.objects.aggregate(total_quantity=Sum('quantity'))
print(total_sales_quantity) # {'total_quantity': Total Quantity}

Annotate Example: Total Sales Quantity per Product

# views.py or shell

from .models import Product


products_with_sales_totals = Product.objects.annotate(total_quantity=Sum('sales__quantity'))
for product in products_with_sales_totals:
print(product.name, product.total_quantity)

This will add a total_quantity attribute to each Product instance, showing the total quantity sold for each product.

Summary

  • Use aggregate for overall calculations like totals, averages, etc., and get a single summary result.
  • Use annotate for per-item calculations to add computed values as attributes to each item in the queryset.

Thank you for reading! If you notice any mistakes or have suggestions for improvement, please leave a comment below.

If you enjoyed this post, please click the 👏 button to help others discover it. You can also follow me on:

GitHub | daily.dev | LinkedIn | YouTube

More library

Django

28 stories

--

--

Mehedi Khan
Mehedi Khan

Written by Mehedi Khan

I'm a Software engineer. I'm comfortable with Python, Django, and Full-stack Web Development. Follow To Support Me On Medium 🫠