Django Admin:检测对象字段的子集是否已更改,以及哪些字段已更改

Django Admin:检测对象字段的子集是否已更改,以及哪些字段已更改,django,django-models,django-admin,django-forms,Django,Django Models,Django Admin,Django Forms,我需要在管理员中检测某些模型的某些字段何时发生了更改,以便稍后根据哪些字段发生了更改以及这些字段的以前/当前值发送通知 我尝试使用ModelForm并重写save()方法,但是表单的self.cleaned_data和seld.instance已经有了字段的新值。在完全保存之前,您需要做的是从save方法内的数据库中获取正在处理的对象的额外副本。例如: class MyModel(models.Model): field1 = models.CharField(max_length=50

我需要在管理员中检测某些模型的某些字段何时发生了更改,以便稍后根据哪些字段发生了更改以及这些字段的以前/当前值发送通知


我尝试使用
ModelForm
并重写
save()
方法,但是表单的
self.cleaned_data
seld.instance
已经有了字段的新值。

在完全保存之前,您需要做的是从save方法内的数据库中获取正在处理的对象的额外副本。例如:

class MyModel(models.Model):
    field1 = models.CharField(max_length=50)

    def save(self):
        if self.id:
            try:
                old = MyModel.objects.get(pk=self.id)
                if old.field1 != self.field1:
                    # Process somehow
            except MyModel.DoesNotExist:
                pass
        super(MyModel, self).save()

为了获得两个模型实例的差异,您也可以使用这个。它与模型实例进行比较并返回更改字典

为了避免额外的数据库查找,我修改了构造函数以记住初始值,并在以后的save方法中使用:

class Package(models.Model):
    feedback = models.IntegerField(default = 0, choices = FEEDBACK_CHOICES)
    feedback_time = models.DateTimeField(null = True)

    def __init__(self, *args, **kw):
        super(Package, self).__init__(*args, **kw)
        self._old_feedback = self.feedback

    def save(self, force_insert=False, force_update=False, *args, **kwargs):
        if not force_insert and self.feedback != self._old_feedback:
            self.feedback_time = datetime.utcnow()
        return super(Package, self).save(force_insert, force_update, *args, **kwargs)

修改上面的答案。。。使用Dominik Szopa的卓越功能并对其进行更改将解决关系更改检测问题:使用以下方法:

def get_changes_between_models(model1, model2, excludes = []):
    changes = {}
    for field in model1._meta.fields:
        if not (field.name in excludes):
            if field.value_from_object(model1) != field.value_from_object(model2):
                changes[field.verbose_name] = (field.value_from_object(model1),
                                                   field.value_from_object(model2))
    return changes
然后在代码中可以说(避免尝试/出于性能原因除外):


如果在“模型”级别执行此操作,则无法保存额外的查询。当您到达“保存”点时,数据已经更改。我的第一篇帖子,请原谅我听起来像个白痴。

我也提出了类似的想法(在保存对象之前从数据库中检索对象,并将其与即将保存的副本进行比较),但我想保存额外的查询。这很有用!但它似乎不知道相关的领域。出于我的目的,添加或删除关系(一对多或多对多)也是对对象的更改。感谢您提供有关
字段的提示。value\u from\u object()
!显然,它提供了一种一致的比较值的方法。美好的为了使这个答案更具可读性、精确性和清晰性,我将“model1”改为“model\u instance\u 1”,将“model2”改为“model\u instance\u 2”。方法名称可能应该是“在模型和实例之间获取变化”。不确定在django的最新版本中是否有更好的方法,但我目前使用的是1.8,这个答案对我来说适用。在我看来,在很多情况下,这并不能满足您的需要。例如,在表单提交时,从POST参数初始化对象,然后保存。保存方法不会在初始字段值和当前字段值之间找到差异;但它们与数据库中的不同。
if (self.id):
    old = MyModel.Objects.get(pk=self.id)
    changes = get_changes_between_models(self, old)

    if (changes):
        # Process based on what is changed.