📖 Теория: Сериализаторы DRF

⚡ Ключевые концепции

  • ModelSerializer — автоматически создаёт поля из модели Django
  • Read-сериализатор: вложенные объекты через SomeSerializer(read_only=True)
  • Write-сериализатор: FK-ключи через fields = '__all__', только ID
  • read_only_fields = ['created_at', 'deleted'] — запрет изменения служебных полей
  • validate_<field>(self, value) — кастомная валидация на уровне поля

ModelSerializer: основы

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

from rest_framework import serializers
from .models import Category

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = '__all__'  # все поля модели

Паттерн: два сериализатора на модель

В REST API часто разделяют сериализаторы на две роли:

Тип Назначение Связанные объекты
ReadSerializer GET — возвращает данные клиенту Вложенные объекты (read_only=True)
CreateUpdateSerializer POST/PUT/PATCH — принимает данные от клиента Только FK (первичные ключи)

Read-сериализатор с вложенными объектами

class ProductSerializer(serializers.ModelSerializer):
    category = CategorySerializer(read_only=True)  # вложенный объект
    supplier = SupplierSerializer(read_only=True)  # вложенный объект

    class Meta:
        model = Product
        fields = '__all__'

Поле read_only=True означает: при десериализации (POST/PUT) это поле игнорируется. Оно только для вывода.

Write-сериализатор с FK

class ProductCreateUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'
        # category и supplier принимаются как числовые ID (FK)

read_only_fields

Некоторые поля устанавливаются автоматически Django (например, date_joined, order_date) и не должны быть изменяемы через API. Используйте read_only_fields:

class OrderSerializer(serializers.ModelSerializer):
    class Meta:
        model = Order
        fields = '__all__'
        read_only_fields = ['order_date']  # устанавливается автоматически

Кастомная валидация полей

Метод validate_<field_name> вызывается автоматически при десериализации. Если валидация не прошла — нужно вызвать serializers.ValidationError.

import re

class CustomerCreateUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Customer
        fields = ['first_name', 'last_name', 'email', 'phone_number', 'address']

    def validate_phone_number(self, value):
        if not re.match(r'^\d{10,15}$', value):
            raise serializers.ValidationError(
                'Номер телефона должен содержать от 10 до 15 цифр.'
            )
        return value
Примечание: Паттерн ^\d{10,15}$ — строка должна содержать только цифры (0-9) длиной от 10 до 15 символов. Никаких пробелов, дефисов или скобок.

Валидация числового поля

class OrderItemCreateUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = OrderItem
        fields = '__all__'

    def validate_quantity(self, value):
        if value > 1000:
            raise serializers.ValidationError(
                'Количество товара должно быть не больше тысячи.'
            )
        return value

Ограничение доступных полей в write-сериализаторе

Для модели Customer write-сериализатор не включает служебные поля (date_joined, deleted, deleted_at) — они просто не перечислены в fields:

class CustomerCreateUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Customer
        fields = ['first_name', 'last_name', 'email', 'phone_number', 'address']
        # date_joined, deleted, deleted_at — отсутствуют намеренно
← К оглавлению урока    Справочник →