← Назад к вопросам
Как мы получаем модель, если сериализатор (serializer) уже заполнен?
2.0 Middle🔥 171 комментариев
#Soft Skills
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Как мы получаем модель, если сериализатор (serializer) уже заполнен
Это вопрос о паттерне работы с сериализаторами в Django REST Framework (DRF) и как преобразовать валидированные данные в модель объекта.
Базовый поток: Data → Serializer → Model
Обычный процесс выглядит так:
from rest_framework import serializers
from myapp.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email']
# 1. Получаем JSON данные
data = {'username': 'john', 'email': 'john@example.com'}
# 2. Передаём в сериализатор
serializer = UserSerializer(data=data)
# 3. Валидируем
if serializer.is_valid():
# 4. Получаем модель — вот тут несколько вариантов
user = serializer.save() # Сохраняет в БД и возвращает User объект
Способ 1: .save() — сохранить и получить модель
Это самый простой способ — валидированные данные сразу сохраняются в БД:
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save() # Возвращает User объект
return Response({'id': user.id})
Как это работает под капотом:
class ModelSerializer(Serializer):
def save(self, **kwargs):
validated_data = {**self.validated_data, **kwargs}
if self.instance is None:
# Create mode — новый объект
self.instance = self.Meta.model.objects.create(**validated_data)
else:
# Update mode — обновляем существующий
for attr, value in validated_data.items():
setattr(self.instance, attr, value)
self.instance.save()
return self.instance
Способ 2: .validated_data — получить очищенные данные без сохранения
Иногда нужны данные БЕЗ сохранения в БД:
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
# Получаем очищенные данные
validated_data = serializer.validated_data
print(validated_data) # OrderedDict([('username', 'john'), ('email', 'john@example.com')])
# Создаём модель БЕЗ сохранения
user = User(**validated_data) # commit=False эффект
# Можно делать дополнительные операции
user.is_active = True
user.save() # Сохраняем сам
Способ 3: Кастомный create() метод
Когда логика создания сложнее:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username', 'email', 'password']
def create(self, validated_data):
# Кастомная логика создания
password = validated_data.pop('password')
user = User(**validated_data)
user.set_password(password) # Хэшируем пароль
user.save()
return user
# Использование:
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save() # Вызывает create()
Способ 4: Кастомный update() метод
Для обновления существующей модели:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username', 'email']
def update(self, instance, validated_data):
# instance — существующий User
instance.username = validated_data.get('username', instance.username)
instance.email = validated_data.get('email', instance.email)
instance.save()
return instance
# Использование:
user = User.objects.get(id=1)
serializer = UserSerializer(user, data=request.data, partial=True)
if serializer.is_valid():
updated_user = serializer.save() # Вызывает update()
Способ 5: Instance mode (Partial update)
Когда нужно обновить конкретный объект (partial update):
# PATCH запрос — обновляем только переданные поля
user = User.objects.get(id=1)
serializer = UserSerializer(
user,
data={'email': 'newemail@example.com'},
partial=True # Не требует все поля!
)
if serializer.is_valid():
updated_user = serializer.save()
return Response(UserSerializer(updated_user).data)
Способ 6: Получение модели из вложенного сериализатора
Когда есть nested relationships:
class AddressSerializer(serializers.ModelSerializer):
class Meta:
model = Address
fields = ['city', 'country']
class UserSerializer(serializers.ModelSerializer):
address = AddressSerializer()
class Meta:
model = User
fields = ['username', 'address']
def create(self, validated_data):
address_data = validated_data.pop('address')
# Создаём Address первым
address = Address.objects.create(**address_data)
# Потом User
user = User.objects.create(address=address, **validated_data)
return user
# Использование:
data = {
'username': 'john',
'address': {'city': 'Moscow', 'country': 'Russia'}
}
serializer = UserSerializer(data=data)
if serializer.is_valid():
user = serializer.save() # Возвращает User с nested Address
Способ 7: Получить модель и дополнительные данные
Вернуть модель + дополнительный контекст:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username', 'email']
def create(self, validated_data):
user = User.objects.create(**validated_data)
return user
# В view:
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
return Response({
'user': UserSerializer(user).data,
'message': 'User created successfully',
'id': user.id
})
Способ 8: Работа с to_representation()
Когда нужна специальная сериализация после сохранения:
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username', 'email']
def to_representation(self, instance):
# После создания модели — специальное отображение
data = super().to_representation(instance)
data['full_name'] = f"{instance.first_name} {instance.last_name}"
return data
# Использование:
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
user = serializer.save()
# to_representation() вызывается автоматически в return
return Response(serializer.data)
Важные моменты
1. .is_valid() обязателен:
# Плохо — использование без валидации
user = User(**serializer.data)
# Хорошо
if serializer.is_valid():
user = serializer.save()
2. Разница между .data и .validated_data:
# .validated_data — очищенные входные данные (не сохранённые)
validated_data = serializer.validated_data
# .data — сериализованный output (результат to_representation)
response_data = serializer.data
3. Instance vs Data:
# Создание (нет instance)
serializer = UserSerializer(data=request.data)
# Обновление (есть instance)
user = User.objects.get(id=1)
serializer = UserSerializer(user, data=request.data)
4. Вариант с transaction для атомарности:
from django.db import transaction
serializer = UserSerializer(data=request.data)
if serializer.is_valid():
with transaction.atomic():
user = serializer.save()
# Другие операции
return Response(serializer.data)