我如何知道django模型实例是否被修改?

时间:2012-05-02 12:27:06

标签: django django-models

我有这样的代码:

# ...
obj = Model.objects.get(pk=2342)
if foo:
    obj.foo = 'bar'
if bar:
    obj.bar = 'baz'
obj.save()

是否有一种很好的方法可以确定是否修改了模型实例,以防止每次代码运行时都保存它?

4 个答案:

答案 0 :(得分:4)

典型的模式是做类似的事情:

model = Model.objects.get(pk=2342)
dirty = False
if foo:
    model.foo = 'bar'
    dirty = True
if bar:
    model.bar = 'baz'
    dirty = True

if dirty:
    model.save()

答案 1 :(得分:1)

只需逐个字段地展示当前模型实例的'snapshot'实例,就可以获得snapshotcopy.copy(obj)model_cls.objects.get(pk=obj.pk)

您也可以简单地比较转储版本:

from django.core.serializers.json import Serializer
dump = Serializer.serialize([obj])
...
changed = dump == Serializer.serialize([obj])

通常情况下,调整代码最简单:

obj = Model.objects.get(pk=2342) # 'obj' is better than 'model', IMO
changed = False
if foo:
    ...
    obj.foo = 'bar'
    changed = True
if bar:
    ...
    obj.bar = 'baz'
    changed = True
if changed:
    obj.save()    

答案 2 :(得分:0)

Django在内部执行此检查。除非模型实际发生了变化,否则不会触发SQL查询。

<强>更新

这个答案是对的。我的错。我把这与别的东西混淆了。

答案 3 :(得分:0)

要以更抽象的方式执行此操作,请查看模型方法from_db()的文档,该模型方法是将数据从数据库加载到模型实例中时调用的钩子。使用此方法,您可以在加载字段时缓存其原始值,然后将其与save()方法中的当前值进行比较。

示例(注意,我尚未实际测试此代码):

class SaveIfModified(models.Model):
    foo = models.TextField()

    @classmethod
    def from_db(cls, db, field_names, values):
        instance = super().from_db(db, field_names, values)
        # caveat: deferred values won't appear here
        if "foo" in field_names:
            instance._foo = values[field_names.index("foo")]
        return instance

    def save(self, *args, **kwargs):
        if self.foo == getattr(self, "_foo", None):
            return
        super().save(*args, **kwargs)