JavaRush /Курсы /Модуль 3: Django /Введение в агрегации в Django ORM

Введение в агрегации в Django ORM

Модуль 3: Django
10 уровень , 0 лекция
Открыта

Прежде чем мы окунемся в код, давайте разберемся с теорией. Агрегации в контексте работы с данными — это процессы, которые позволяют нам "сжать" данные для получения обобщенных результатов. Если мы хотим узнать, сколько у нас пользователей, какова средняя цена товаров в интернет-магазине или сколько заданий выполнено, агрегации станут вашими друзьями.

В SQL это функции, вроде COUNT, SUM, AVG, MAX, MIN. Django ORM предлагает удобную возможность использовать их, не теряя магии Python.

Зачем нужны агрегации?

Представьте, вы на складе, а там — тысячи коробок. Вам нужно подсчитать общее количество коробок красного цвета. Вместо того чтобы вручную пересчитывать коробки и записывать результаты (или выполнять несколько запросов к базе), вы просто агрегируете данные. Это не только экономит время, но и улучшает производительность работы с базой данных.

Простой пример агрегации

Давайте начнем с базового примера. У нас есть модель Product, представляющая товары в интернет-магазине.

from django.db import models

class Product(models.Model):
    name = models.CharField(max_length=100)
    price = models.DecimalField(max_digits=10, decimal_places=2)
    quantity = models.IntegerField()

Допустим, база данных уже заполнена несколькими товарами. Нам нужно найти, сколько всего товаров на складе.

В Django ORM это выглядит следующим образом:

from django.db.models import Sum

total_quantity = Product.objects.aggregate(Sum('quantity'))
print(total_quantity)
# Выведет: {'quantity__sum': 150} (например)

Что мы видим в коде?

  1. Мы вызвали метод .aggregate() на QuerySet.
  2. Внутри .aggregate() мы использовали функцию Sum, чтобы подсчитать общее количество.
  3. Результат возвращается в виде словаря, где ключ — это имя поля (quantity__sum по умолчанию).

И всё! Мы сделали наш первый агрегатный запрос. Красота, не так ли?

Как работает функция .aggregate()

Чтобы лучше понять, как работает метод .aggregate(), давайте разберем процесс шаг за шагом.

  • .aggregate() выполняет один запрос к базе данных и возвращает одну строку с результатами.
  • Он не возвращает объекты модели, а сразу выдает вычисленные значения.
  • Вы можете комбинировать несколько агрегатных функций в одном запросе.

Пример с несколькими агрегатными функциями:

from django.db.models import Sum, Avg

result = Product.objects.aggregate(
    total_quantity=Sum('quantity'),
    average_price=Avg('price')
)
print(result)
# Выведет: {'total_quantity': 150, 'average_price': Decimal('25.30')}

Обратите внимание на то, что для удобства мы указали кастомные ключи (total_quantity, average_price), чтобы их значения было проще использовать.

Почему .aggregate() лучше, чем обычный Python?

У вас может возникнуть вопрос: "Зачем использовать .aggregate()? Разве нельзя просто достать все данные и посчитать их в Python?"

Ответ краток: можно, но не нужно. Причина в том, что .aggregate() позволяет перенести вычисления на уровень базы данных, что экономичнее. База данных оптимизирована для подобных операций, поэтому такая реализация будет быстрее и менее ресурсозатратной.

Пример неправильного подхода:

total_quantity = sum(product.quantity for product in Product.objects.all())

Этот код:

  1. Достает все записи из базы данных, что может быть очень медленно, если данных много.
  2. Выполняет вычисления в Python, перегружая вашу память.

Пример правильного подхода, как мы уже видели ранее:

total_quantity = Product.objects.aggregate(Sum('quantity'))

Этот запрос выполняется только на уровне базы данных и возвращает результат сразу. Быстро, удобно и элегантно!

Основные сценарии использования агрегаций

Давайте рассмотрим, где можно применять агрегации в реальных приложениях:

  1. Интернет-магазины:

    • Подсчитать общее количество продаж.
    • Подсчитать общую сумму покупок.
  2. Социальные сети:

    • Количество лайков под постами.
    • Среднее количество комментариев на пост.
  3. Работа с пользователями:

    • Количество активных пользователей.
    • Средний возраст пользователей.

Пример для подсчета количества активных пользователей:

from django.db.models import Count

active_users = User.objects.filter(is_active=True).aggregate(Count('id'))
print(active_users)
# Выведет: {'id__count': 42}

Ошибки при использовании .aggregate()

Конечно, путь программиста усеян граблями. Вот несколько из них — типичные ошибки:

  1. Забыли вызвать .filter() до .aggregate() Если вы хотите агрегировать данные только для определенной группы записей, не забудьте добавить фильтр:

    total_sales = Product.objects.filter(is_sold=True).aggregate(Sum('quantity'))
    

    Если вы забудете .filter(), то агрегируется все, а не только ожидаемые записи.

  2. Попытка использовать .aggregate() после .all() Помните, .aggregate() вызывается на QuerySet сразу, а не после .all(). Иначе будет ошибка.

  3. Неявное использование имён полей По умолчанию Django добавляет __sum, __avg и прочее к именам полей. Поэтому, если вы хотите использовать конкретный ключ, укажите его в явном виде:

    result = Product.objects.aggregate(total=Sum('quantity'))
    print(result['total'])  # Так проще!
    

Практическое задание

Самостоятельно напишите агрегатный запрос в вашей текущей учебной модели (или создайте новую модель). Вот несколько идей:

  • Подсчитайте общее количество записей в модели.
  • Найдите максимальную цену товара.
  • Вычислите среднее количество чего-либо.

Пример:

from django.db.models import Max

max_price = Product.objects.aggregate(Max('price'))
print(max_price)
# Например: {'price__max': Decimal('100.00')}

Что дальше?

Теперь, когда вы понимаете основы агрегаций и умеете использовать .aggregate(), вы готовы к более сложным техникам: аннотациям, сложным фильтрациям и использованию Q-объектов. Мы продолжим изучение этих тем в следующих лекциях.

1
Задача
Модуль 3: Django, 10 уровень, 0 лекция
Недоступна
Подсчёт количества пользователей
Подсчёт количества пользователей
1
Задача
Модуль 3: Django, 10 уровень, 0 лекция
Недоступна
Общая стоимость заказов
Общая стоимость заказов
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Александр Уровень 67
19 ноября 2025
Во второй задаче нужно выводить результат в представлении (views.py).