Ответ
В 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()
сводит весь набор данных к одному итоговому значению.