⚖️ Устаревшие паттерны → современный синтаксис
Паттерны из лекции, которые работают, но уже не актуальны в Django 5.x / DRF 3.x
⚡ Основные изменения
- Подсчёт через aggregate:
.aggregate(Count('id'))['id__count']→ просто.count() - Сериализатор PUT:
Serializer(instance, data)→Serializer(instance, data=request.data) - Функциональные views без DRF:
HttpResponse(json.dumps(...))→JsonResponse(..., safe=False) - Response() vs JsonResponse: в новом DRF чаще используют
Response()из DRF, а неJsonResponse
1. Подсчёт объектов
Из лекции (старое)
# Через aggregate — избыточно
from django.db.models import Count
result = Project.objects.aggregate(Count('id'))
count = result['id__count']
print(count)
Современный стиль
# Прямой метод count() — проще и читаемее
count = Project.objects.all().count()
print(count)
# Или просто:
count = Project.objects.count()
2. PUT-сериализатор — передача данных
Из лекции (старое — работает, но неявно)
# Позиционный аргумент data — неявно
validated_data = TagsSerializer(tag, request.data)
if validated_data.is_valid(raise_exception=True):
validated_data.save()
Современный стиль (явные аргументы)
# Явная передача data= и partial= (для PATCH)
serializer = TagsSerializer(tag, data=request.data)
if serializer.is_valid(raise_exception=True):
serializer.save()
# PATCH — частичное обновление
serializer = TagsSerializer(tag, data=request.data, partial=True)
if serializer.is_valid(raise_exception=True):
serializer.save()
3. JsonResponse vs DRF Response
Из лекции (JsonResponse — Django)
from django.http import JsonResponse
from rest_framework import status
return JsonResponse(
serialized_data.data,
status=status.HTTP_200_OK,
safe=False # обязательно для списков!
)
Современный стиль (DRF Response)
from rest_framework.response import Response
from rest_framework import status
# Response умеет сам работать со списками
# и поддерживает content negotiation (JSON, XML, ...)
return Response(
serialized_data.data,
status=status.HTTP_200_OK
)
Response() из DRF предпочтительнее для DRF-проектов: поддерживает content negotiation, работает с renderers, не требует safe=False. JsonResponse — стандартный Django, работает, но менее гибок в контексте DRF.
4. Проверка пустого QuerySet
Из лекции (работает, но неоптимально)
# Python-истинность QuerySet
if cur_month_projects:
for proj in cur_month_projects:
...
Современный стиль
# exists() — эффективнее: SELECT 1 LIMIT 1
if cur_month_projects.exists():
for proj in cur_month_projects:
...
# В view-функциях — также exists()
if not all_projects.exists():
return JsonResponse([], status=204, safe=False)
if queryset: вычисляет QuerySet целиком (делает SELECT), .exists() выполняет более легкий запрос SELECT 1 LIMIT 1.
5. Подсчёт файлов для проекта — aggregate vs annotate
Из лекции (через Python-цикл)
# Цикл + aggregate для каждого проекта
projects = Project.objects.all()
project_file_counts = {}
for project in projects:
file_count = project.project_files.aggregate(
num_files=Count('id')
)
project_file_counts[project.name] = file_count['num_files']
Современный стиль (один SQL-запрос)
# annotate выполняет один запрос с GROUP BY
projects = Project.objects.annotate(
num_files=Count('project_files')
)
for p in projects:
print(f"{p.name}: {p.num_files} files")
Подход из лекции делает N+1 запросов (один на каждый проект).
annotate() делает один запрос с GROUP BY — существенно эффективнее при большом числе проектов.
6. AVG — импорт
Из лекции (некорректный импорт)
# В лекции написано: "Импортируйте класс AVG из django"
# Такого класса нет!
from django import AVG # ошибка
Правильный импорт
# Класс называется Avg (с маленькой 'vg'), из django.db.models
from django.db.models import Avg
Project.objects.annotate(avg_tasks=Avg('tasks__id'))
В лекции написано "импортируйте класс AVG из django" — это опечатка. Правильно:
from django.db.models import Avg (с заглавной A и строчными vg).