MyModel.objects.update_or_create() - >布尔数据是否已更新?

gue*_*tli 8 django django-models

AFAIK Django没有提供通用方法来查看update_or_create()是否更改了数据

布尔created告诉我创建了一行.但是我怎么知道数据是否被更改(更新数据的SQL UPDATE)

例:

obj, created = MyModel.update_or_create(pk=12345,
                       defaults=dict(name='Doctor Zhivago'))
Run Code Online (Sandbox Code Playgroud)

有三种情况:

  1. obj创建了.没问题,我有布尔变量created
  2. obj没有创建,它已更新.例如,之前的名字是"Machuca".
  3. obj没有创建,也没有更新.例如,之前的名字已经是"日瓦戈医生".

我目前无法区分case2和case3.

A. *_*arr 6

感觉有点受@bakkal启发,我写了一个mixin类,你可以将它应用于自定义Manager类,然后将该自定义Manager分配给你的MyModel类.这会将返回的元组的格式更改为(obj, created, updated).在循环中的值defaults.items()我正在检查是否有任何新值与旧值不同.

class UpdateOrCreateMixin(object):
    def update_or_create_v2(self, defaults=None, **kwargs):
        """
        Look up an object with the given kwargs, updating one with defaults
        if it exists, otherwise create a new one.
        Return a tuple (object, created, updated), where created and updated are 
        booleans specifying whether an object was created.
        """
        defaults = defaults or {}
        lookup, params = self._extract_model_params(defaults, **kwargs)
        self._for_write = True
        with transaction.atomic(using=self.db):
            try:
                obj = self.select_for_update().get(**lookup)
            except self.model.DoesNotExist:
                obj, created = self._create_object_from_params(lookup, params)
                if created:
                    return obj, created, False
            updated = False
            for k, v in defaults.items():
                oldattr = getattr(obj, k)
                if oldattr != (v() if callable(v) else v):
                    updated = True
                setattr(obj, k, v() if callable(v) else v)
            obj.save(using=self.db)
        return obj, False, updated

class CustomManager(UpdateOrCreateMixin, models.Manager):
    pass

class MyModel(models.Model)
    field = models.CharField(max_length=32)
    objects = CustomManager()

obj, created, updated = MyModel.objects.update_or_create_v2(pk=12345,
                   defaults=dict(name='Doctor Zhivago'))
Run Code Online (Sandbox Code Playgroud)