← Назад к вопросам
В каком случае вызывается update в сериализаторе (serializer)
2.0 Middle🔥 191 комментариев
#Django#REST API и HTTP
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# Метод update() в Django REST Framework сериализаторе
Метод update() в сериализаторе вызывается в одном конкретном случае: когда нужно обновить существующий объект в БД. Сейчас подробнее разберу, когда и как это происходит.
Основной принцип
Есть два основных метода для создания/обновления объектов:
create()— создаёт новый объектupdate()— изменяет существующий объект
Django REST Framework автоматически выбирает нужный метод в зависимости от того, передаём ли мы объект при инициализации сериализатора.
Когда вызывается update()
Случай 1: Сериализатор инициализирован с instance
Если при создании сериализатора передаём существующий объект:
from rest_framework import serializers
from .models import Article
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ['id', 'title', 'content', 'created_at']
def update(self, instance, validated_data):
"""Вызывается при обновлении существующей статьи"""
instance.title = validated_data.get('title', instance.title)
instance.content = validated_data.get('content', instance.content)
instance.save()
return instance
# В представлении
from rest_framework.response import Response
from rest_framework.views import APIView
class ArticleUpdateView(APIView):
def put(self, request, pk):
article = Article.objects.get(pk=pk) # получаем существующий объект
# ЗДЕСЬ ВЫЗЫВАЕТСЯ update(), потому что передаём instance
serializer = ArticleSerializer(article, data=request.data)
if serializer.is_valid():
serializer.save() # вызывает update(instance, validated_data)
return Response(serializer.data)
return Response(serializer.errors, status=400)
Случай 2: Обновление через ViewSet
from rest_framework import viewsets
class ArticleViewSet(viewsets.ModelViewSet):
queryset = Article.objects.all()
serializer_class = ArticleSerializer
# При PUT запросе на /articles/1/ автоматически:
# 1. Получает объект Article с pk=1
# 2. Инициализирует сериализатор с instance=article
# 3. Вызывает update() при save()
Сравнение: create vs update
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ['id', 'title', 'content']
def create(self, validated_data):
"""Вызывается при создании НОВОГО объекта"""
print("CREATE вызывается")
return Article.objects.create(**validated_data)
def update(self, instance, validated_data):
"""Вызывается при обновлении СУЩЕСТВУЮЩЕГО объекта"""
print("UPDATE вызывается")
instance.title = validated_data.get('title', instance.title)
instance.save()
return instance
# СОЗДАНИЕ (create)
data = {'title': 'New Article', 'content': 'Text'}
serializer = ArticleSerializer(data=data) # БЕЗ instance
if serializer.is_valid():
serializer.save() # вызывает create()
# OUTPUT: "CREATE вызывается"
# ОБНОВЛЕНИЕ (update)
article = Article.objects.first()
data = {'title': 'Updated Title', 'content': 'New Text'}
serializer = ArticleSerializer(article, data=data) # С instance
if serializer.is_valid():
serializer.save() # вызывает update()
# OUTPUT: "UPDATE вызывается"
Как Django REST Framework решает, какой метод вызвать
# В базовом классе Serializer
class Serializer:
def save(self, **kwargs):
"""
Сохранение или обновление объекта на основе наличия instance
"""
if self.instance is not None:
# Объект был передан при инициализации → ОБНОВЛЕНИЕ
self.instance = self.update(self.instance, self.validated_data)
else:
# Объект не передан → СОЗДАНИЕ
self.instance = self.create(self.validated_data)
return self.instance
Практический пример: обновление с custom логикой
from rest_framework import serializers
from .models import User, Profile
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['id', 'username', 'email']
def update(self, instance, validated_data):
# Можем добавить custom логику
email_changed = validated_data.get('email') != instance.email
# Обновляем поля
instance.username = validated_data.get('username', instance.username)
instance.email = validated_data.get('email', instance.email)
instance.save()
# Если email изменился, отправляем подтверждение
if email_changed:
send_email_verification(instance.email)
return instance
Обновление с вложенными объектами
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = Comment
fields = ['id', 'text', 'author']
class ArticleSerializer(serializers.ModelSerializer):
comments = CommentSerializer(many=True, read_only=False)
class Meta:
model = Article
fields = ['id', 'title', 'comments']
def update(self, instance, validated_data):
comments_data = validated_data.pop('comments', [])
# Обновляем саму статью
instance.title = validated_data.get('title', instance.title)
instance.save()
# Обновляем связанные комментарии
for comment_data in comments_data:
comment_id = comment_data.get('id')
if comment_id:
comment = Comment.objects.get(id=comment_id)
comment.text = comment_data.get('text', comment.text)
comment.save()
return instance
Важные моменты
1. Разница между PUT и PATCH
# PUT — обновление всех полей (полная замена)
# instance передаётся → вызывается update()
data = {'title': 'New Title', 'content': 'New Content'}
serializer = ArticleSerializer(article, data=data, partial=False)
# PATCH — обновление только переданных полей
# instance передаётся → вызывается update()
data = {'title': 'New Title'} # content не меняется
serializer = ArticleSerializer(article, data=data, partial=True)
2. Частичное обновление
def update(self, instance, validated_data):
# partial=True позволяет обновлять только переданные поля
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
return instance
3. Обновление с доступом к request
class ArticleSerializer(serializers.ModelSerializer):
class Meta:
model = Article
fields = ['id', 'title', 'content']
def update(self, instance, validated_data):
# Можем получить доступ к request
request = self.context.get('request')
user = request.user if request else None
# Логируем, кто обновил
instance.updated_by = user
instance.title = validated_data.get('title', instance.title)
instance.save()
return instance
Резюме: когда вызывается update()
context: нет instance
serializer = Serializer(data=data) → save() вызовет create()
context: есть instance
serializer = Serializer(instance, data=data) → save() вызовет update()
В ViewSet:
POST /articles/ → create()
GET /articles/1/ → retrieve() (ничего не сохраняется)
PUT /articles/1/ → update()
PATCH /articles/1/ → partial_update()
DELETE /articles/1/ → destroy()
Метод update() вызывается только когда обновляем существующий объект, в отличие от create(), который создаёт новый.