💻 Примеры: паттерны сериализаторов DRF

⚡ Ключевые паттерны

# Read + Write пара для Product
class ProductSerializer(serializers.ModelSerializer):
    category = CategorySerializer(read_only=True)
    supplier = SupplierSerializer(read_only=True)
    class Meta:
        model = Product
        fields = '__all__'

class ProductCreateUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'  # category, supplier = ID

# read_only_fields
class OrderSerializer(serializers.ModelSerializer):
    customer = CustomerSerializer(read_only=True)
    class Meta:
        model = Order
        fields = '__all__'
        read_only_fields = ['order_date']

# Валидация
def validate_quantity(self, value):
    if value > 1000:
        raise serializers.ValidationError('Не более 1000')
    return value

Пример 1: Базовый CRUD-сериализатор

Простейший случай — когда модель не имеет связей или они не нужны во вложенном виде:

# store/serializers.py
from rest_framework import serializers
from .models import Category, Supplier, Address

class CategorySerializer(serializers.ModelSerializer):
    class Meta:
        model = Category
        fields = '__all__'

class SupplierSerializer(serializers.ModelSerializer):
    class Meta:
        model = Supplier
        fields = '__all__'

class AddressSerializer(serializers.ModelSerializer):
    class Meta:
        model = Address
        fields = '__all__'

Такие сериализаторы работают для всех операций: GET, POST, PUT, PATCH, DELETE.

Пример 2: Read/Write пара для Product

from rest_framework import serializers
from .models import Product, Category, Supplier

# Для GET — возвращает вложенные объекты
class ProductSerializer(serializers.ModelSerializer):
    category = CategorySerializer(read_only=True)
    supplier = SupplierSerializer(read_only=True)

    class Meta:
        model = Product
        fields = '__all__'

# Для POST/PUT/PATCH — принимает category_id, supplier_id
class ProductCreateUpdateSerializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'
Как DRF принимает FK: Когда в ProductCreateUpdateSerializer поле category не переопределено, DRF автоматически создаёт PrimaryKeyRelatedField — принимает числовой ID категории.

Пример 3: read_only_fields — защита служебных полей

from rest_framework import serializers
from .models import Order, Customer

class OrderSerializer(serializers.ModelSerializer):
    customer = CustomerSerializer(read_only=True)

    class Meta:
        model = Order
        fields = '__all__'
        read_only_fields = ['order_date']
        # order_date устанавливается автоматически (auto_now_add=True)
        # и не должна меняться через API

Пример 4: Кастомная валидация телефона

import re
from rest_framework import serializers
from .models import Customer

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

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

Метод validate_phone_number вызывается автоматически, когда DRF обрабатывает поле phone_number. При ошибке — 400 Bad Request с сообщением.

Пример 5: Валидация числового поля quantity

from rest_framework import serializers
from .models import OrderItem

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

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

Пример 6: Вложенность нескольких уровней

Сериализатор OrderItemSerializer включает вложенные ProductSerializer и OrderSerializer, каждый из которых в свою очередь включает свои вложенные объекты:

class OrderItemSerializer(serializers.ModelSerializer):
    product = ProductSerializer(read_only=True)   # nested: Product -> Category, Supplier
    order = OrderSerializer(read_only=True)        # nested: Order -> Customer -> Address

    class Meta:
        model = OrderItem
        fields = '__all__'
Производительность: Глубокая вложенность вызывает N+1 запросов. В реальных проектах используйте select_related() и prefetch_related() в QuerySet view'а. Для практикума — допустимо.

Пример 7: Использование сериализаторов во view

from rest_framework.views import APIView
from rest_framework.response import Response
from .models import Product
from .serializers import ProductSerializer, ProductCreateUpdateSerializer

class ProductAPIView(APIView):
    def get(self, request):
        products = Product.objects.select_related('category', 'supplier').all()
        serializer = ProductSerializer(products, many=True)
        return Response(serializer.data)

    def post(self, request):
        serializer = ProductCreateUpdateSerializer(data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=201)
        return Response(serializer.errors, status=400)
← К оглавлению урока    Задания →