📖 Теория: Сериализаторы 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 — отсутствуют намеренно