当commit = False时调用Django pre_save信号

时间:2009-06-13 20:33:27

标签: django model-view-controller signals models

我正在编写一个Django应用程序,它将跟踪模型的更改,与管理界面类似。例如,我将能够显示模型的更改列表,其类似于Changed Status from Open to Closed

我正在使用pre_save信号执行此操作,比较数据库中现有项目与正在保存的“实例”之间的相关字段。要获得现有项目,我必须做sender._default_manager.get(pk=sender.pk)这看起来有点乱,但那部分有效。

问题是,更改此模型的视图调用表单上的save()方法两次(首先使用commit = False) - 这意味着在数据库中记录了2个更改,因为发出了pre_save信号两次。

有什么方法可以做到这一点吗?也许完全以不同的方式,虽然我记得读过Django管理员应用程序使用信号来跟踪用户所做的更改。

3 个答案:

答案 0 :(得分:3)

浏览Django源代码,即使pre_savecommit,似乎每次保存调用都会发送false个信号。我建议在第一个pre_save上插入,但在更改表中添加一个标志列,例如

class FooChanges(models.Model):
    foo = models.ForeignKey(Foo)
    dt = models.DateTimeField(default=datetime.now)
    field = models.CharField(max_length=50)
    value = models.CharField(max_length=50) # Or whatever is appropriate here
    finished = models.BooleanField(default=False)

然后,你的预设可以是:

def pre_save_handler(sender, instance):
    foo_changes, created = FooChanges.objects.get_or_create(foo=instance, finished=False, field='Status', value=instance.status)
    if not created:
        foo_changes.finished = True
        foo_changes.save()

因此,在第一个pre_save上,您实际插入了更改。在第二遍中,您从数据库中检索它,并将该标志设置为false,以确保在下次Foo的{​​{1}}更改时不会将其取出。

答案 1 :(得分:1)

答案 2 :(得分:0)

Django审核日志

django-audit-log是一款可插拔的应用,可以轻松完成您想要的任务。我已经在一个项目中使用它了,我现在肯定会使用它了。我知道它。