DRF doc say's我需要覆盖序列化程序create
和update
方法来更新和/或创建嵌套数据。但是,当我尝试编辑现有的descriptions
时,我的代码会创建一个新代码。有没有一种简单的方法可以检测哪些描述是编辑的,只更新它?
class TaskSerializer(ModelSerializer):
url = HyperlinkedIdentityField(
view_name='tasks:tasks-detail',
lookup_field='pk',
)
author = SlugField(source='author.username')
executor = SlugField(source='executor.username')
descriptions = DescriptionSerializer(many=True)
class Meta:
model = Task
fields = (
'pk',
'url',
'title',
'project',
'status',
'author',
'executor',
'descriptions'
)
def create(self, validated_data):
descriptions_data = validated_data.pop('descriptions', None)
author = validated_data.pop('author', None)
executor = validated_data.pop('executor', None)
try:
task_author = User.objects.get(username=author['username'])
task_executor = User.objects.get(username=executor['username'])
except User.DoesNotExist:
raise ValidationError(
_("Такого пользователя не сущетсвует!"))
task = Task.objects.create(author=task_author, executor=task_executor, **validated_data)
if descriptions_data:
for description in descriptions_data:
description, created = Description.objects.get_or_create(
text=description['text'],
task=task
)
task.descriptions.add(description)
return task
def update(self, instance, validated_data):
descriptions_data = validated_data.pop('descriptions', None)
instance.title = validated_data.get('title', instance.title)
instance.project = validated_data.get('project', instance.project)
instance.status = validated_data.get('status', instance.status)
author = validated_data.pop('author', None)
executor = validated_data.pop('executor', None)
try:
if author:
task_author = User.objects.get(username=author['username'])
instance.author = task_author
if executor:
task_executor = User.objects.get(username=executor['username'])
instance.executor = task_executor
except User.DoesNotExist:
raise ValidationError(
_("Такого пользователя не сущетсвует!"))
descriptions_list = []
if descriptions_data:
for description in descriptions_data:
description, created = Description.objects.get_or_create(
text=description["text"],
task=instance
)
descriptions_list.append(description)
instance.descriptions.set(descriptions_list)
instance.save()
return instance
class DescriptionSerializer(ModelSerializer):
class Meta:
model = Description
fields = (
'pk',
'text',
)
class Task(models.Model):
STATUS_CHOICES = (
(1, _("В процессе разработки")),
(2, _("В процессе тестирования")),
(3, _("На ревью")),
(4, _("Открыта")),
(5, _("Закрыта"))
)
title = models.CharField(_('Название'), max_length=60)
project = models.CharField(_('Название проекта'), max_length=60)
status = models.IntegerField(_('Статус'), choices=STATUS_CHOICES,
default=4)
author = models.ForeignKey(settings.AUTH_USER_MODEL,
max_length=60, on_delete=models.CASCADE,
related_name='author',
verbose_name=_('Автор'),
validators=[validate_user])
executor = models.ForeignKey(settings.AUTH_USER_MODEL,
max_length=60, on_delete=models.CASCADE,
related_name='executor',
verbose_name=_('Исполнитель'),
validators=[validate_user])
def __str__(self):
return self.title
def __unicode__(self):
return u'{}'.format(self.title)
class Meta:
verbose_name = _('Задача')
verbose_name_plural = _('Задачи')
class Description(models.Model):
task = models.ForeignKey(Task, on_delete=models.CASCADE,
related_name='descriptions')
text = models.TextField(_('Описание'))
def __str__(self):
return '#{}'.format(self.pk)
def __unicode__(self):
return u'#{}'.format(self.pk)
class Meta:
verbose_name = _('Описание')
verbose_name_plural = _('Описания')