✅ Решения — Урок 26
⚡ Ответы
- 1.1: 1→B, 2→A, 3→D, 4→C, 5→E
- 2.1: C —
order_by('-field_name') - 3.1: B —
Subquery - 3.2: A —
OuterRef - 3.3: 1→C, 2→D, 3→A, 4→B
- 4.1: B — преобразование сложных структур в простые форматы
- 4.2: C — Модели базы данных (не часть DRF)
Решения — блок «Агрегация»
Задание 1.1 — Сопоставление функций агрегации
Ответ: 1→B, 2→A, 3→D, 4→C, 5→E
Count→ B (Подсчитывает количество записей)Sum→ A (Вычисляет сумму значений)Avg→ D (Вычисляет среднее значение)Min→ C (Нахождение минимального значения)Max→ E (Нахождение максимального значения)
Задание 1.2 — aggregate vs annotate
# Вызов A — возвращает ОДИН словарь для всего QuerySet
result_a = Book.objects.aggregate(total=Count('id'))
# Результат: {'total': 42} — одно число для всей таблицы
# Вызов B — возвращает QuerySet, где каждый элемент — группа
result_b = Book.objects.values('author').annotate(cnt=Count('id'))
# Результат: [
# {'author': 1, 'cnt': 5},
# {'author': 2, 'cnt': 3},
# ...
# ] — каждый автор получает свой счётчик
Ключевое отличие: aggregate() возвращает одно итоговое значение; annotate() добавляет поле к каждому объекту/группе.
Решения — блок «order_by и срезы»
Задание 2.1
Ответ: C — order_by('-field_name')
Минус перед именем поля в строке — сортировка по убыванию. Вариант B без кавычек и минуса вызовет NameError.
Задание 2.2 — Срезы
# Места 6–15 по цене (дорогие): отсортировать по убыванию, взять [5:15]
expensive_books = Book.objects.order_by('-price')[5:15]
# Пояснение:
# order_by('-price') — сортировка по убыванию цены
# [5:15] — пропустить 5 первых, взять следующие 10
# SQL: ORDER BY price DESC LIMIT 10 OFFSET 5
Решения — блок «Подзапросы»
Задание 3.1
Ответ: B — Subquery
Subquery оборачивает QuerySet, делая его подзапросом. OuterRef — для ссылки на внешний запрос, Avg — агрегационная функция.
Задание 3.2
Ответ: A — OuterRef
OuterRef('field') ссылается на значение поля из внешнего (главного) запроса внутри подзапроса. Это позволяет создавать коррелированные подзапросы.
Задание 3.3 — Сопоставление классов
Ответ: 1→C, 2→D, 3→A, 4→B
ExpressionWrapper→ C (Оборачивает сложные выражения, указывает тип данных)Avg→ D (Вычисляет среднее значение поля)Subquery→ A (Включает результаты одного QuerySet в другой)OuterRef→ B (Ссылается на поля из внешнего запроса)
Решения — блок «DRF»
Задание 4.1
Ответ: B — Процесс преобразования сложных структур данных в простые форматы.
Вариант A — это десериализация (обратный процесс). Вариант C — это валидация.
Задание 4.2
Ответ: C — Модели базы данных.
Модели — это часть Django ORM, а не DRF. DRF работает поверх Django и использует уже готовые модели. Сериализаторы и Views — это компоненты DRF.
Решения — Практические задания
Задание 5.1 — Издательства с более чем 3 книгами
from django.db.models import Count
publishers = Publisher.objects.annotate(
book_count=Count('book') # обратная связь через related_name или имя модели в нижнем регистре
).filter(
book_count__gt=3
).order_by('-book_count')
for pub in publishers:
print(f"{pub.name}: {pub.book_count} книг")
Пояснение: Count('book') использует обратную связь от Publisher к Book (Django автоматически создаёт связь по имени модели в нижнем регистре). filter(book_count__gt=3) — фильтрация по аннотированному полю.
Задание 5.2 — TaskSerializer
# serializers.py
from rest_framework import serializers
from .models import Task
class TaskSerializer(serializers.ModelSerializer):
class Meta:
model = Task
fields = ['id', 'title', 'description', 'status', 'deadline', 'created_at']
read_only_fields = ['id', 'created_at']
Пояснение:
ModelSerializerавтоматически создаёт поля из моделиfields— явно перечисляем, какие поля включитьread_only_fields—idназначается БД,created_atзадаётсяauto_now_add=True- При создании задачи через POST эти поля игнорируются во входных данных