Sitemap

Django Aggregate vs Annotate with example

2 min readJul 27, 2024
Press enter or click to view image in full size
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

38 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 🫠

No responses yet