⚖️ Старый vs Новый — Урок 26

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

Паттерны из лекции (Django 3.x / DRF 3.x) → актуальный Django 5.x + DRF 3.15+

⚡ Главные отличия

  • Агрегации и annotate() — API не изменился, работает в Django 3–5
  • Subquery/OuterRef — введены в Django 1.11, актуальны в 5.x
  • DRF: старый Serializer с ручными полями → современный ModelSerializer
  • Старые function-based views с ручным json.dumps()@api_view + Response

1. Агрегации — API стабилен

Методы aggregate(), annotate(), функции Count, Sum, Avg, Min, MaxAPI не менялся с Django 2.x. Код из лекции корректен в Django 5.x.

ЧтоСтатус
aggregate(total=Count('id'))Актуально, без изменений
annotate(book_count=Count('id'))Актуально, без изменений
ExtractYear, ExtractQuarterАктуально, добавлены в Django 2.0

2. Подзапросы — API стабилен с Django 1.11

Subquery и OuterRef введены в Django 1.11, полностью поддерживаются в Django 5.x без изменений.

# Из лекции (Django 3.x) — актуально в Django 5.x
from django.db.models import OuterRef, Subquery, Min

subquery = Book.objects.filter(
    author=OuterRef('author')
).values('author').annotate(
    min_price=Min('price')
).values('min_price')
books = Book.objects.annotate(min_author_price=Subquery(subquery))
# Работает без изменений в Django 5.x

3. ExpressionWrapper — стабилен, но есть нюанс

Старый подход (лекция)Современный подход
# Иногда пропускали output_field
Book.objects.annotate(
    diff=ExpressionWrapper(
        F('price') - F('discounted_price'),
        output_field=fields.DecimalField()  # было опциональным
    )
)
# Django 5.x: output_field обязателен
# для смешанных типов (int/float/decimal)
Book.objects.annotate(
    diff=ExpressionWrapper(
        F('price') - F('discounted_price'),
        output_field=fields.DecimalField(
            max_digits=10, decimal_places=2
        )
    )
)

4. DRF: сериализатор — от ручного к ModelSerializer

Лекция показывает концепцию сериализации в общем. В реальной разработке используется ModelSerializer:

Старый (ручной Serializer)Современный (ModelSerializer)
# Ручное перечисление всех полей
class BookSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(max_length=100)
    price = serializers.DecimalField(
        max_digits=10, decimal_places=2
    )
    published_date = serializers.DateField()

    def create(self, validated_data):
        return Book.objects.create(**validated_data)

    def update(self, instance, validated_data):
        instance.title = validated_data.get(
            'title', instance.title
        )
        instance.save()
        return instance
# ModelSerializer автоматически создаёт поля
class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = ['id', 'title', 'price', 'published_date']
        read_only_fields = ['id']
# create() и update() встроены автоматически

5. DRF: представления — от ручного JSON к @api_view + Response

Устаревший подход (Django views)Современный (DRF @api_view)
# Без DRF — ручная сериализация
import json
from django.http import JsonResponse

def book_list(request):
    books = list(Book.objects.values(
        'id', 'title', 'price'
    ))
    return JsonResponse({'books': books})
# С DRF — автоматическая сериализация
from rest_framework.decorators import api_view
from rest_framework.response import Response

@api_view(['GET'])
def book_list(request):
    books = Book.objects.all()
    serializer = BookSerializer(books, many=True)
    return Response(serializer.data)

6. DRF: статус-коды — от числа к константам

Старый (числа)Современный (константы)
return Response(data, status=201)
return Response(errors, status=400)
return Response({}, status=404)
from rest_framework import status

return Response(data, status=status.HTTP_201_CREATED)
return Response(errors, status=status.HTTP_400_BAD_REQUEST)
return Response({}, status=status.HTTP_404_NOT_FOUND)

Константы из rest_framework.status делают код самодокументирующимся.

7. order_by по связанным полям

В лекции встречается устаревший синтаксис без двойного подчёркивания:

Из лекции (может не работать)Актуальный Django 5.x
# Без двойного подчёркивания
books = Book.objects.order_by('author', 'title')
# Сортирует по id автора, не по имени!
# Через двойное подчёркивание — по имени автора
books = Book.objects.order_by('author__name', 'title')
# Правильная сортировка по имени автора
⚠️ Проверить по документации: в Django 5.x добавлены новые возможности для annotate() с условными выражениями (Case/When). Для более сложных сценариев см. официальную документацию.