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-об'єктів. Ми продовжимо вивчення цих тем у наступних лекціях.

Коментарі
ЩОБ ПОДИВИТИСЯ ВСІ КОМЕНТАРІ АБО ЗАЛИШИТИ КОМЕНТАР,
ПЕРЕЙДІТЬ В ПОВНУ ВЕРСІЮ