Django使用PUT方法更新外键数据

时间:2018-05-20 13:21:49

标签: django django-rest-framework put

DRF doc say's我需要覆盖序列化程序createupdate方法来更新和/或创建嵌套数据。但是,当我尝试编辑现有的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 = _('Описания')

0 个答案:

没有答案