Django:何时定制 save 方法 vs 使用 post-save 信号?

27
我有一系列的测试和案例放在数据库中。每当一个测试过时了,它就会被终止日期,那么任何该测试的子测试也应该被终止日期。我看到两种方法可以实现这个功能:
1)修改保存函数来结束子测试。
2)创建一个接收器监听被保存的测试模型,并终止其子测试。
有什么理由使用其中一种而不是另一种吗?
编辑: 我看到这篇博客文章建议在检查模型的给定值时使用save方法。由于我正在检查end_date,这是否意味着我应该使用自定义save?
编辑2: 此外,记录完整层次结构为:Protocol-> Test-> Case-> Planned_Execution,任何一个测试被终止日期,每个子项都必须被终止日期。 我想我最终会为每个子项执行基本相同的操作。
编辑3: 实际上为了确定当前save()是将Test设置为终止日期的,我需要访问旧数据和新数据,所以我使用了自定义save。其代码如下:
def save(self):
    """Use a custom save to end date any subCases"""
    try:
        orig = Test.objects.get(id=self.id)
        enddated = (not orig.end_date) and self.end_date is not None   
    except:
        enddated = False

    super(Test, self).save()

    if enddated:
        for case in self.case_set.exclude(end_date__isnull=False):
            case.end_date = self.end_date
            case.enddater = self.enddater
            case.save()

2
我想补充一点,你应该在save方法中接受*args和**kwargs,并将它们传递给super,以防有人想使用像update_save或force_insert这样的参数。 - ShawnFumo
2个回答

30

我通常使用以下的经验法则:

  • 如果你必须修改数据以使保存成功,那么覆盖save()(事实上没有其他选择)。例如,在我正在开发的应用程序中,我有一个带有选项列表的文本字段的模型。这个文本字段与旧代码进行交互,并替换了一个具有类似文本字段的较老模型,但是带有一份不同的选项列表。旧代码有时会向我的模型传递旧模型的选项,但是这些选项之间存在1:1的映射关系,因此在这种情况下,我可以修改所选的选项为新模型的选项。这样做在save()中很有意义。
  • 否则,如果保存可以无需干预就能继续进行,我通常使用后保存信号。

5
更明确地说,当您需要操作对象本身时,请使用“save”。这意味着您的对象方法在代码的其他地方具有较少的“副作用”,这使得维护更容易。 - adamnfish

16

在我看来,信号是解耦模块的一种手段。由于您的任务似乎只发生在一个模块中,我会定制保存操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接