如果我这样做:
obj = Model.objects.get(pk=2)
object.field = 'new value'
object.save()
它运行我在django中编写的自定义保存方法。
但是,如果我执行正常的更新声明:
Model.objects.filter(pk=2).update(field='new value')
它不使用自定义保存方法。我的问题是双重的:
update
个语句?基本上,我只想确保在django ORM中进行保存时,自定义保存方法始终运行。怎么会这样呢?答案 0 :(得分:2)
我不是Django开发人员,但我时不时地讨论,还没有人回答。
为什么在django中做出了这个决定 - 为什么不是每个'save'都实现自定义保存方法。
我将在这里猜测,这是针对仅执行批量更新的常见情况进行的速度优化。 update
works on the SQL level所以它可能比在许多对象上调用save
要快得多,每个对象都是自己的数据库事务。
是否有代码库范围的方法来确保没有更新语句?基本上,我只想确保在django ORM中进行保存时始终运行自定义保存方法。这怎么可能?
您可以将custom manager与自定义QuerySet一起使用,只要调用update
,就会引发一些异常。当然,如果您需要自定义行为,可以总是遍历Queryset并在每个对象上调用save
。
from django.db import models
class NoUpdateQuerySet(models.QuerySet):
"""Don't let people call update! Muahaha"""
def update(self, **kwargs):
# you should raise a more specific Exception.
raise Exception('You shall not update; use save instead.')
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
# setting the custom manager keeps people from calling update.
objects = NoUpdateQuerySet.as_manager()
您只需要将NoUpdateQuerySet设置为您不想更新的每个模型的管理器。我不认为有必要设置自定义QuerySet;如果是我,我就不会调用update,并在需要时循环遍历需要保存的对象。您可能会找到想要来调用更新的时间,这最终会导致非常烦恼。
如果您确实决定讨厌update
,那么您可以对更新方法进行修补。然后你可以完全确定它没有被调用。您可以在项目的settings.py
中对其进行修补,因为您知道该模块将被导入:
def no_update(self, **kwargs):
# probably want a more specific Exception
raise Exception('NO UPDATING HERE')
from django.db.models.query import QuerySet
QuerySet.update = no_update
请注意,回溯实际上会非常混乱,因为它将指向settings.py
中的函数。我不确定其他应用程序使用了多少update
。这可能会产生意想不到的后果。