Django:在模型更新之前,我想"看看"它以前的属性

ano*_*ard 13 django django-signals django-models

当对Django模型(.save())执行更新/创建时,我希望能够"介入"并将某些特定属性与之前设置的属性进行比较(如果它们以前存在的话).

我正在考虑预先保存信号,查看原始模型做的事情.objects.get(instance.id),但这感觉很浪费.还有,验证已经发生了pre_save()吗?

seb*_*piq 7

关于模型验证:

请注意,调用模型的save()方法时,不会自动调用full_clean()

然后,关于pre-save signal,请注意您将正在保存的实例作为参数与消息一起发送.由于您的模型的旧版本仅存在于数据库中,因此我看不到您可以在哪里获得以前的属性值...

你不明白为什么要这样做,所以很难说,但我现在正在考虑的其他解决方案:

* defining a custom signal that is sent everytime the attributes you are interested in are modified... This signal would then send two arguments : new value, old value
* perform the check directly when setting the attributes
Run Code Online (Sandbox Code Playgroud)

如果你提供更多细节,可能会更容易......

编辑:

这是正确的......如果你发出自定义'foo_has_updated',你将不确定是否保存了修改.

在这种情况下,我猜你可以在初始化实例时缓存你感兴趣的变量,并捕获保存后的OR预保存信号.

* With pre-save, you would be able to pre-process the data, but the saving operation might fail
* With post-save, you would be sure that the data has been saved.
Run Code Online (Sandbox Code Playgroud)

缓存您的变量可以这样做:

class CachedModel(models.Model):
    cached_vars = [var1, var2, varN]
    def __init__(self, *args, **kwargs):
        super(CachedModel, self).__init__(*args, **kwargs)
        self.var_cache = {}
        for var in self.cached_vars:
            self.var_cache[var] = copy.copy(getattr(self, var))
Run Code Online (Sandbox Code Playgroud)

或类似的东西......然后,在你的信号处理程序中:

def post_save_handler(sender, **kwargs):
    instance = kwargs["instance"]
    [(instance.var_cache[var], getattr(instance, var)) for var in instance.cached_var]
    #[(<initial value>, <saved value>)
Run Code Online (Sandbox Code Playgroud)

你得到了你需要的东西(我想)!