修改类方法是应该保存自己还是在调用方法后显式调用?

时间:2010-06-26 19:14:43

标签: python django

假设一个类有一个修改它内部的方法。 该方法应该在返回之前调用自身保存还是应该在调用修改方法后将保存留给调用者显式保存?

示例:

明确地调用save:

class Bar(models.Model):
    def set_foo(self, foo):
        self.foo = foo

bar = Bar()
bar.set_foo("foobar")
bar.save()

或允许方法调用save:

class Bar(models.Model):
    def set_foo(self, foo):
        self.foo = foo
        self.save()

bar = Bar()
bar.set_foo("foobar")

我正在和django一起工作,但我想知道django或者一般情况下这种情况是否有最好的做法。

4 个答案:

答案 0 :(得分:3)

您的API的用户可能希望进行多项更改,在每次更改之后保存对象都是好的,所以不要,不要在方法中调用save。

答案 1 :(得分:2)

您的API用户可能忘记调用.save()然后搞砸了。所以我认为最好为他打电话。对于Daslch提到的案例,如果有意义,你可以定义:

def set_foo(self, foo, skip_save=False):
    self.foo = foo
    if not skip_save:
        self.save()

所以如果用户愿意(并明确说明),用户可以避免保存。

答案 2 :(得分:1)

实际上,我同意Ofri和Daslch ......取决于一周的哪一天。如果这只是您可能对特定对象执行的许多修改例程之一,那么每个修改例程都会自行保存。另一方面,如果这是一个罕见的,自包含的事件,那么你想要进行保存,因为它对调用者来说可能并不明显(即以外的其他人需要它完成。

例如,标记事件(无论如何都使用ManyToMany)应该不需要程序员部分的额外save()。

答案 3 :(得分:0)

为了处理各种现有答案中表达的所有问题,我建议采用以下方法:制作一个方法,称之为savingmodifying,即上下文管理器。该方法的条目设置一个私有标志,表示修改正在进行中;出口重置标志并执行保存;所有修改方法都会检查标志并在未设置时引发异常。例如,使用基类和实际子类必须覆盖的save方法:

import contextlib

class CarefullyDesigned(object):

    def __init__(self):
      self.__saving = False

    def _save(self):
      raise NotImplementedError('Must override `_save`!')

    def _checksaving(self):
      "Call at start of subclass `save` and modifying-methods"
      if not self.__saving: raise ValueError('No saving in progress!')

    @contextlib.contextmanager
    def saving(self):
      if self.__saving: raise ValueError('Saving already in progress!')
      self.__saving = True
      yield
      self._save()
      self.__saving = False

使用示例......:

class Bar(models.Model, CarefullyDesigned):

    def __init__(self, *a, **k):
        models.Model.__init__(self, *a, **k)
        CarefullyDesigned.__init__(self)

    def _save(self):
        self._checksaving()
        self.save()

    def set_foo(self, foo):
        self._checksaving()
        self.foo = foo

    def set_fie(self, fie):
        self._checksaving()
        self.fie = fie

bar = Bar()
with bar.saving():
    bar.set_foo("foobar")
    bar.set_fie("fo fum")

这可以保证用户不会忘记调用saving,也不会忘记以嵌套的方式调用它(这是所有这些例外的目的),并且当用户组中只调用save一次修改方法是方便的,我会说,非常自然的方式。