⚖️ Устаревшие паттерны → современный синтаксис

Паттерны из лекции, которые работают, но уже не актуальны в 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).

← К оглавлению урока