Ответ
В Django ORM annotate() и aggregate() — это методы QuerySet для выполнения агрегатных функций (таких как Sum, Count, Avg), но они возвращают результаты принципиально разного типа.
annotate() — для каждой записи
- Что делает: Добавляет вычисляемое поле к каждому объекту в
QuerySet. - Что возвращает: Новый
QuerySet, где каждый объект дополнен новым полем. - Аналогия: Добавление нового столбца в таблицу с вычисленным значением для каждой строки (например, «количество заказов у каждого клиента»).
aggregate() — для всего набора
- Что делает: Вычисляет итоговое значение для всего
QuerySet. - Что возвращает: Словарь (
dict) с итоговыми значениями. - Аналогия: Вычисление итоговой суммы или среднего по всему столбцу таблицы (например, «общая сумма всех заказов»).
Практический пример
Предположим, у нас есть модели Author и Book:
from django.db import models
from django.db.models import Count, Avg
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author, on_delete=models.CASCADE, related_name='books')
rating = models.FloatField()
Использование annotate():
Получим количество книг для каждого автора.
# Возвращает QuerySet объектов Author, у каждого из которых есть поле 'num_books'
authors = Author.objects.annotate(num_books=Count('books'))
for author in authors:
# author.name = 'J.K. Rowling', author.num_books = 7
# author.name = 'J.R.R. Tolkien', author.num_books = 3
print(f"{author.name} написал(а) книг: {author.num_books}")
Использование aggregate():
Вычислим средний рейтинг по всем книгам в базе данных.
# Возвращает словарь с одним ключом 'avg_rating'
result = Book.objects.aggregate(avg_rating=Avg('rating'))
# result будет {'avg_rating': 4.25}
print(f"Средний рейтинг всех книг: {result['avg_rating']}")
Вывод: annotate() обогащает каждую запись в наборе данных, а aggregate() сводит весь набор данных к одному итоговому значению.