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

发布于 2024-08-24 04:55:13 字数 201 浏览 5 评论 0原文

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

我尝试使用 ModelForm 并覆盖 save() 方法,但表单的 self.cleaned_dataseld.instance 已经有了字段的新值。

I need to detect when some of the fields of certain model have changed in the admin, to later send notifications depending on which fields changed and previous/current values of those fields.

I tried using a ModelForm and overriding the save() method, but the form's self.cleaned_data and seld.instance already have the new values of the fields.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

一花一树开 2024-08-31 04:55:13

修改上面的答案...从 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

然后在您的代码中您可以说(避免尝试/除非出于性能原因):

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.

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

Modifying the answer above... taking the brilliant function from Dominik Szopa and changing it will solve your relationship change detection: Use this:

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

Then in your code you can say (avoid try/except for performance reasons):

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.

If you are doing this at the "model" level, there is no way to save the extra query. The data has already been changed by the time you reach the "Save" point. My first post, so forgive me if I sound like an idiot.

笑忘罢 2024-08-31 04:55:13

为了避免额外的数据库查找,我修改了构造函数以记住初始值并稍后在 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)

To avoid extra DB lookup, I modified constructor to remember initial value and use this in save method later:

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)
鸩远一方 2024-08-31 04:55:13

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

In order to get differences of two model instances, you can also use this function. It compare to model instances and returns dictionary of changes.

暖伴 2024-08-31 04:55:13

您需要做的是在完全保存之前从 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()

What you'll need to do is get an extra copy of the object you're working on from the database inside the save method before fully saving it. Example:

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()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文