UPDATE不使用模型保存方法

时间:2014-11-19 21:33:27

标签: python django

如果我这样做:

obj = Model.objects.get(pk=2)
object.field = 'new value'
object.save()

它运行我在django中编写的自定义保存方法。

但是,如果我执行正常的更新声明:

Model.objects.filter(pk=2).update(field='new value')

它不使用自定义保存方法。我的问题是双重的:

  • 1)为什么在django中做出了这个决定 - 为什么不是每个'save'都实现自定义保存方法。
  • 2)是否有代码库范围的方法来确保没有发出update个语句?基本上,我只想确保在django ORM中进行保存时,自定义保存方法始终运行。怎么会这样呢?

1 个答案:

答案 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。这可能会产生意想不到的后果。