← Назад к вопросам
В каком случае вызывается create в сериализаторе (serializer)
1.7 Middle🔥 181 комментариев
#Django#REST API и HTTP
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Метод create() в Django REST Framework сериализаторе
Метод create() в сериализаторе — это один из ключевых методов для создания объектов из валидированных данных. Давайте разберёмся, когда и как он вызывается.
Жизненный цикл сериализатора
Прежде всего, нужно понять процесс:
1. Получить данные (JSON от клиента)
↓
2. Валидировать данные (is_valid())
↓
3. Если валиден → вызвать create() или update()
↓
4. Вернуть результат
Когда вызывается create()
Метод create() вызывается только в следующих случаях:
- Вы явно вызваете
.save()на новом сериализаторе (без instance) - Вы используете это в ViewSet с методом POST
- Вы обновляете данные через сериализатор с вызовом
.save()
Случай 1: Явный вызов save() при создании
from rest_framework import serializers
from django.contrib.auth.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email']
def create(self, validated_data):
print("create() вызван!") # ← Это будет выведено
# Здесь создаём объект
return User.objects.create(**validated_data)
# В вашем view или тесте
data = {'username': 'alice', 'email': 'alice@example.com'}
serializer = UserSerializer(data=data) # ← Важно: data= параметр
if serializer.is_valid():
user = serializer.save() # ← Здесь вызывается create()
print(user) # <User: alice>
Ключевой момент: когда передаём data= параметр (без instance=), это признак создания нового объекта.
Случай 2: ModelViewSet с POST
from rest_framework import viewsets
from rest_framework.decorators import api_view
from rest_framework.response import Response
from django.contrib.auth.models import User
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# ViewSet автоматически обрабатывает POST:
# POST /api/users/ → create() вызывается
# Фактически ViewSet это делает:
# if request.method == 'POST':
# serializer = self.serializer_class(data=request.data)
# if serializer.is_valid():
# serializer.save() # ← create() вызывается здесь
Случай 3: Частый баг — update() вместо create()
# НЕПРАВИЛЬНО: это вызовет update(), не create()
user = User.objects.get(id=1)
data = {'username': 'bob'}
serializer = UserSerializer(user, data=data) # ← instance= передан!
if serializer.is_valid():
serializer.save() # ← Вызывает update(), НЕ create()!
Полный пример: когда вызывается create() vs update()
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email', 'first_name']
def create(self, validated_data):
print(f"CREATE: {validated_data}")
return User.objects.create(**validated_data)
def update(self, instance, validated_data):
print(f"UPDATE: {instance} with {validated_data}")
for key, value in validated_data.items():
setattr(instance, key, value)
instance.save()
return instance
# Сценарий 1: Создание нового пользователя
data = {'username': 'alice', 'email': 'alice@example.com', 'first_name': 'Alice'}
serializer = UserSerializer(data=data)
if serializer.is_valid():
serializer.save()
# Вывод: CREATE: {'username': 'alice', ...}
# Сценарий 2: Обновление существующего пользователя
existing_user = User.objects.get(username='alice')
data = {'first_name': 'Alicia'} # Изменяем только first_name
serializer = UserSerializer(existing_user, data=data, partial=True)
if serializer.is_valid():
serializer.save()
# Вывод: UPDATE: <User: alice> with {'first_name': 'Alicia'}
Разница между instance и data параметрами
# 1. Только data= → CREATE
serializer = UserSerializer(data={'username': 'bob'})
if serializer.is_valid():
serializer.save() # create() вызвана
# 2. instance= и data= → UPDATE
user = User.objects.get(id=1)
serializer = UserSerializer(instance=user, data={'username': 'bob'})
if serializer.is_valid():
serializer.save() # update() вызвана
# 3. Только instance= → Нет вызова (просто сериализуем объект для вывода)
user = User.objects.get(id=1)
serializer = UserSerializer(instance=user) # Только чтение
print(serializer.data) # {'id': 1, 'username': 'bob', ...}
Пользовательская логика в create()
Часто в create() нужна дополнительная логика:
Пример 1: Создание связанных объектов
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ['id', 'title', 'content', 'author_id']
def create(self, validated_data):
# Добавляем текущего пользователя как автора
validated_data['author'] = self.context['request'].user
return Post.objects.create(**validated_data)
# В view:
class PostViewSet(viewsets.ModelViewSet):
serializer_class = PostSerializer
def get_serializer_context(self):
context = super().get_serializer_context()
# Передаём request в контекст сериализатора
return context
Пример 2: Хеширование пароля
class UserCreateSerializer(serializers.ModelSerializer):
password = serializers.CharField(write_only=True)
class Meta:
model = User
fields = ['username', 'email', 'password']
def create(self, validated_data):
password = validated_data.pop('password') # Извлекаем пароль
user = User.objects.create(**validated_data)
user.set_password(password) # Хешируем пароль
user.save()
return user
# Использование
data = {'username': 'alice', 'email': 'alice@example.com', 'password': 'secret123'}
serializer = UserCreateSerializer(data=data)
if serializer.is_valid():
user = serializer.save() # create() хеширует пароль
Пример 3: Создание нескольких связанных объектов
class OrderItemSerializer(serializers.ModelSerializer):
class Meta:
model = OrderItem
fields = ['product_id', 'quantity']
class OrderSerializer(serializers.ModelSerializer):
items = OrderItemSerializer(many=True) # Вложенные данные
class Meta:
model = Order
fields = ['id', 'user_id', 'items']
def create(self, validated_data):
items_data = validated_data.pop('items')
# Создаём заказ
order = Order.objects.create(**validated_data)
# Создаём позиции в заказе
for item_data in items_data:
OrderItem.objects.create(order=order, **item_data)
return order
# Использование
data = {
'user_id': 1,
'items': [
{'product_id': 5, 'quantity': 2},
{'product_id': 7, 'quantity': 1}
]
}
serializer = OrderSerializer(data=data)
if serializer.is_valid():
order = serializer.save() # create() создаёт заказ и позиции
Сравнение: явный create() vs автоматический
# 1. Автоматический create() (ModelSerializer)
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username', 'email']
# create() и update() уже реализованы, не переопределяем
# 2. Пользовательский create() (для дополнительной логики)
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['username', 'email']
def create(self, validated_data):
# Добавляем логику до создания
validated_data['email_verified'] = False
user = User.objects.create(**validated_data)
# Отправляем email подтверждения
send_verification_email(user)
return user
# 3. Сериализатор без модели (Serializer)
class ContactSerializer(serializers.Serializer):
name = serializers.CharField(max_length=100)
email = serializers.EmailField()
message = serializers.CharField(max_length=1000)
def create(self, validated_data):
# Нет модели, нужно реализовать вручную
# Например, отправить email
send_contact_email(
to=validated_data['email'],
subject=f"Message from {validated_data['name']}",
body=validated_data['message']
)
# Или сохранить в БД вручную
Contact.objects.create(**validated_data)
return validated_data
Важные моменты
1. Контекст в create()
def create(self, validated_data):
# Вы можете получить доступ к request
user = self.context['request'].user
print(user) # Текущий пользователь
# Используйте это для привязки к текущему пользователю
validated_data['created_by'] = user
return Post.objects.create(**validated_data)
2. Исключения в create()
def create(self, validated_data):
try:
return User.objects.create(**validated_data)
except IntegrityError:
raise serializers.ValidationError({
'username': 'Пользователь с таким именем уже существует'
})
3. Atomicity: все или ничего
from django.db import transaction
def create(self, validated_data):
with transaction.atomic(): # Если ошибка — откатываем всё
order = Order.objects.create(**validated_data)
for item_data in validated_data['items']:
OrderItem.objects.create(order=order, **item_data)
return order
Проверка: как понять, вызовется ли create()
# Проверка 1: есть ли data параметр?
serializer = UserSerializer(data=request.data) # ← ДА → create()
serializer = UserSerializer(instance=user) # ← НЕТ → нет create()
# Проверка 2: есть ли instance параметр?
serializer = UserSerializer(data=request.data) # ← instance НЕТ → create()
serializer = UserSerializer(user, data=request.data) # ← instance ЕСТЬ → update()
# Проверка 3: вызывается ли save()?
serializer.is_valid() # Просто валидируем
serializer.save() # ← Это вызывает create() или update()
Заключение
create() в сериализаторе вызывается когда:
✅ Вы передали только data= параметр (без instance=)
✅ Вы вызвали .save() на сериализаторе
✅ Обычно в POST запросах (создание новых объектов)
Это место для:
- Дополнительной валидации
- Специальной логики при создании
- Создания связанных объектов
- Отправки уведомлений
- Логирования событий