我正在编写一个Django应用程序,它将跟踪模型的更改,与管理界面类似。例如,我将能够显示模型的更改列表,其类似于Changed Status from Open to Closed
。
我正在使用pre_save信号执行此操作,比较数据库中现有项目与正在保存的“实例”之间的相关字段。要获得现有项目,我必须做sender._default_manager.get(pk=sender.pk)
这看起来有点乱,但那部分有效。
问题是,更改此模型的视图调用表单上的save()
方法两次(首先使用commit = False) - 这意味着在数据库中记录了2个更改,因为发出了pre_save信号两次。
有什么方法可以做到这一点吗?也许完全以不同的方式,虽然我记得读过Django管理员应用程序使用信号来跟踪用户所做的更改。
答案 0 :(得分:3)
浏览Django源代码,即使pre_save
为commit
,似乎每次保存调用都会发送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-audit-log是一款可插拔的应用,可以轻松完成您想要的任务。我已经在一个项目中使用它了,我现在肯定会使用它了。我知道它。