5

我有这样的代码:

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

有没有一种好方法可以找出模型实例是否被修改以防止每次代码运行时都保存它?

4

4 回答 4

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()
于 2012-05-02T14:27:28.693 回答
1

只需逐个字段区分带有当前模型实例的“快照”实例,您就可以snapshot通过copy.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()    
于 2012-05-02T14:09:14.253 回答
0

Django 在内部执行此检查。除非模型实际更改,否则不会触发 sql 查询。

更新

这个答案是错误的。我的错。我把它和别的东西混淆了。

于 2012-05-02T12:33:51.160 回答
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)
于 2019-10-03T02:14:27.423 回答