Django-Rest框架正在更新嵌套的m2m对象。有人知道更好的方法吗?

2024-04-19 14:27:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个例子,当用户需要更新一个instance,同时在这个实例上添加/编辑与m2m相关的对象。在

我的解决方案是:

# models.py

class AdditionalAction(SoftDeletionModel):
    ADDITIONAL_CHOICES = (
        ('to_bring', 'To bring'),
        ('to_prepare', 'To prepare'),
    )
    title = models.CharField(max_length=50)
    type = models.CharField(choices=ADDITIONAL_CHOICES, max_length=30)

class Event(models.Model):
     title= models.CharField(max_length=255)
     actions = models.ManyToManyField(AdditionalAction, blank=True)



# serializers.py
class MySerializer(serializers.ModelSerializer):
    def update(self, instance, validated_data):
        actions_data = validated_data.pop('actions')

        # Use atomic block to rollback if anything raised Exception 
        with transaction.atomic():

            # update main object
            updated_instance = super().update(instance, validated_data)

            actions = []
            # Loop over m2m relation data and
            # create/update each action instance based on id present
            for action_data in actions_data:
                action_kwargs = {
                    'data': action_data
                }
                id = action_data.get('id', False)
                if id:
                    action_kwargs['instance'] = AdditionalAction.objects.get(id=id)
                actions_ser = ActionSerializerWrite(**action_kwargs)
                actions_ser.is_valid(raise_exception=True)
                actions.append(actions_ser.save())

            updated_instance.actions.set(actions)

        return updated_instance

有人能提出更好的解决方案吗?在

p.S.操作在本例中可以创建或更新,所以我不能在序列化程序上使用many=True,因为它也需要instance来更新。


Tags: toinstanceactionsidtruedatamodelsupdate
1条回答
网友
1楼 · 发布于 2024-04-19 14:27:35

如果你有一个很长的列表或者在save上触发的操作,那么在这里使用for循环将是一个杀手,我会尽量避免它。 最好使用带有where子句的ORMS update:https://docs.djangoproject.com/en/2.0/topics/db/queries/#updating-multiple-objects-at-once,甚至在写入后从数据库中读取更新的对象。在

要创建新操作,可以使用bulk\u create:https://docs.djangoproject.com/en/2.0/ref/models/querysets/#bulk-create

还有一个是:https://github.com/aykut/django-bulk-update(免责声明:我不是包的贡献者或作者)。在

你必须意识到这种方法的缺点-如果你使用任何后/预保存信号,这些信号不会被更新触发。在

一般来说,运行多个存储会杀死数据库,最终可能会出现难以诊断的死锁。在其中一个项目中,我将循环中的save()移到update()中,将响应时间从30秒缩短到<;10秒,此时发送电子邮件的操作最长。在

相关问题 更多 >