DjangoJuniorCoding

Что такое Django REST Framework (DRF) и как работают сериализаторы?

DRF — библиотека для построения REST API на Django; сериализаторы преобразуют модели в JSON и обратно, выполняют валидацию через is_valid() и сохраняют данные через save(), вызывающий create() или update().

Что такое Django REST Framework

Django REST Framework (DRF) — это библиотека поверх Django, предоставляющая инструменты для построения Web API: сериализаторы, generic views, viewsets, routers, аутентификацию, пермиссии и пагинацию. Устанавливается через pip и регистрируется в INSTALLED_APPS.

pip install djangorestframework
# settings.py
INSTALLED_APPS = [
    ...
    "rest_framework",
]

Что делают сериализаторы

Сериализатор выполняет три задачи:

  • Сериализация — преобразует Python-объект (модель Django, queryset) в примитивный словарь, который затем JSON-энкодер превращает в байты.
  • Десериализация и валидация — принимает входные данные (из запроса), проверяет их и возвращает очищенные значения через validated_data.
  • Сохранение — через методы create() и update() записывает данные в базу.

Базовый Serializer

from rest_framework import serializers


class ArticleSerializer(serializers.Serializer):
    id = serializers.IntegerField(read_only=True)
    title = serializers.CharField(max_length=255)
    published = serializers.BooleanField(default=False)
    created_at = serializers.DateTimeField(read_only=True)

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

    def update(self, instance, validated_data):
        instance.title = validated_data.get("title", instance.title)
        instance.published = validated_data.get("published", instance.published)
        instance.save()
        return instance

ModelSerializer — быстрый путь

ModelSerializer автоматически генерирует поля из модели Django, избавляя от ручного перечисления. Достаточно указать модель и список полей.

from rest_framework import serializers
from .models import Article


class ArticleSerializer(serializers.ModelSerializer):
    class Meta:
        model = Article
        fields = ["id", "title", "published", "created_at"]
        read_only_fields = ["id", "created_at"]

    def validate_title(self, value):
        """Валидация одного поля."""
        if len(value) < 5:
            raise serializers.ValidationError("Title must be at least 5 characters.")
        return value

    def validate(self, attrs):
        """Кросс-полевая валидация."""
        if attrs.get("published") and not attrs.get("title"):
            raise serializers.ValidationError("Published articles must have a title.")
        return attrs

Использование сериализатора в view

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Article
from .serializers import ArticleSerializer


@api_view(["GET", "POST"])
def article_list(request):
    if request.method == "GET":
        articles = Article.objects.all()
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)

    elif request.method == "POST":
        serializer = ArticleSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()  # вызывает create()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Вложенные сериализаторы и связи

Для ForeignKey и M2M DRF предоставляет несколько вариантов представления: первичный ключ (PrimaryKeyRelatedField), строковое представление (StringRelatedField) или вложенный сериализатор.

class AuthorSerializer(serializers.ModelSerializer):
    class Meta:
        model = Author
        fields = ["id", "name"]


class ArticleSerializer(serializers.ModelSerializer):
    author = AuthorSerializer(read_only=True)  # вложенный объект
    author_id = serializers.PrimaryKeyRelatedField(
        queryset=Author.objects.all(), source="author", write_only=True
    )

    class Meta:
        model = Article
        fields = ["id", "title", "author", "author_id"]

Подводные камни

  • N+1 запросы с вложенными сериализаторами. Каждый вложенный объект без select_related/prefetch_related генерирует отдельный SQL-запрос. Всегда оптимизируйте queryset в view.
  • fields = "__all__" в Meta. Удобно для прототипа, но легко случайно экспонировать чувствительные поля (пароль, токены). Всегда явно перечисляйте поля.
  • is_valid() без raise_exception. Если забыть вызвать is_valid() перед обращением к validated_data, Django бросит AssertionError. Используйте serializer.is_valid(raise_exception=True) в API-views.
  • create()/update() не вызываются автоматически. save() вызывает их косвенно; если нужна транзакция, оберните в transaction.atomic() внутри метода.
  • Вложенная запись без кастомных create/update. DRF по умолчанию не умеет создавать связанные объекты через вложенные сериализаторы при записи — нужно переопределять методы вручную.
  • SerializerMethodField и производительность. Каждое поле типа SerializerMethodField вызывает Python-функцию на каждый объект; при большом queryset это заметно.

Common mistakes

  • Описывать drf serializers только как термин и не показывать механизм на минимальном примере.
  • Игнорировать ошибки, пустые данные, конкурентный доступ или границы транзакции.
  • Не связывать поведение с официальным контрактом Django и реальной эксплуатацией.

What the interviewer is testing

  • Объясняет drf serializers через последовательность действий, а не через набор ключевых слов.
  • Приводит короткий кодовый пример или production-сценарий с ожидаемым поведением.
  • Называет хотя бы один риск: производительность, безопасность, транзакции, память или сопровождение.

Sources

Related topics