🔖 Справочник: Практикум 6

⚡ Шпаргалка

# Агрегация одного значения
Model.objects.aggregate(alias=Func(F('field')))['alias']

# Группировка + аннотация
Model.objects.values('group_field').annotate(alias=Func('field')).order_by('group_field')

# ExpressionWrapper для вычисления разницы дат
.annotate(lifetime=ExpressionWrapper(F('end') - F('start'), output_field=fields.DurationField()))

# order_by
.order_by('-price')                    # убывание
.order_by('country', 'city')          # несколько полей
.annotate(cnt=Count('items')).order_by('-cnt')  # по аннотации

# Временные метки
one_month_ago = timezone.now() - timezone.timedelta(days=30)
Order.objects.filter(order_date__gte=one_month_ago)

# Срезы
Model.objects.all()[:5]
Model.objects.order_by('-price')[:10]

Агрегирующие функции

Функция Описание Импорт
Sum(expr)Сумма значенийdjango.db.models
Avg(expr)Среднее значениеdjango.db.models
Min(expr)Минимальное значениеdjango.db.models
Max(expr)Максимальное значениеdjango.db.models
Count(expr)Количество объектов/значенийdjango.db.models

Паттерны агрегации

# Паттерн 1: aggregate — одно значение
from django.db.models import Sum, F
result = Product.objects.aggregate(
    total_value=Sum(F('price') * F('quantity'))
)['total_value']

# Паттерн 2: values + annotate — группировка
from django.db.models import Avg
avg_by_cat = Product.objects.values('category__name').annotate(
    average_price=Avg('price')
).order_by('category__name')

# Паттерн 3: Min / Max через aggregate
from django.db.models import Min, Max
extremes = Product.objects.aggregate(
    min_price=Min('price'),
    max_price=Max('price')
)

# Паттерн 4: Count через annotate
from django.db.models import Count
by_supplier = Product.objects.values('supplier__name').annotate(
    product_count=Count('id')
).order_by('supplier__name')

ExpressionWrapper

from django.db.models import Avg, F, ExpressionWrapper, fields
from store.models import ProductDetail

# Вычислить разницу дат как DurationField
avg_lifetime = ProductDetail.objects.annotate(
    lifetime=ExpressionWrapper(
        F('expiration_date') - F('manufacturing_date'),
        output_field=fields.DurationField()
    )
).aggregate(average_lifetime=Avg('lifetime'))['average_lifetime']

# Результат — объект timedelta; .days — количество дней
print(avg_lifetime.days)

order_by

# Один критерий, убывание
Product.objects.order_by('-price')

# Несколько критериев
Address.objects.order_by('country', 'city')

# По аннотированному полю
Order.objects.annotate(
    total=Sum(F('order_items__price') * F('order_items__quantity'))
).order_by('-total')

Order.objects.annotate(
    item_count=Count('order_items')
).order_by('-item_count')

Временные метки

from django.utils import timezone
from store.models import Order

# Один месяц назад
one_month_ago = timezone.now() - timezone.timedelta(days=30)

# Фильтр: дата >= one_month_ago
recent = Order.objects.filter(order_date__gte=one_month_ago)

# Другие временные lookups
Order.objects.filter(order_date__year=2024)
Order.objects.filter(order_date__month=6)
Order.objects.filter(order_date__date=timezone.now().date())

Срезы QuerySet

# Первые N записей
Product.objects.all()[:5]
Product.objects.all()[:10]

# Комбинация с order_by
Product.objects.order_by('-price')[:10]    # топ-10 дорогих

# Диапазон [start:stop] — OFFSET + LIMIT
Product.objects.all()[10:20]  # с 11-й по 20-ю
После применения среза QuerySet нельзя применять filter(), order_by() или другие методы, изменяющие запрос. Применяйте срез последним.

Настройка данных (Интро к практикуму)

# В Django shell: загрузить тестовые данные
python manage.py shell

from store_data import *
export_data()
← К оглавлению урока    Примеры →