我有一个例子,当用户需要更新一个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
来更新。
如果你有一个很长的列表或者在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秒,此时发送电子邮件的操作最长。在
相关问题 更多 >
编程相关推荐