【问题标题】:django - How to customise Model save method when a specified field is changeddjango - 如何在指定字段更改时自定义模型保存方法
【发布时间】:2017-02-23 09:23:06
【问题描述】:

我有一个模型,我们保存A,定义如下:

class A(models.Model):
   name = models.CharField('name', max_length=10)
   enabled = models.BooleanField('enabled', default=False)
   field1 = models.CharField('field1', max_length=10)
   field2 = models.CharField('field2', max_length=10)
   field3 = models.CharField('field3', max_length=10)
   parent = models.ForeignKey('self', null=True, blank=True) # hierarchy

和这个模型的一些对象实例,a,b,c,d。层次结构由父字段表示。

a 
|-- b
    |-- c
    |-- d

所以,我需要做的是,当b.enabledFalse 更改为True,或反之亦然时,我需要将c.enabledd.enabled 更新为值:b.enabled

也就是说,当父级的enabled 字段发生更改时,我需要将更改广播给子级实例。

出于性能考虑,我只需要在enabled 字段真正更改时才广播更改。并且不希望在保存父级时总是更新子实例,例如只更新 field1 或 field2。

那么,有谁知道,实现这个逻辑的最佳方式是什么?提前致谢。

【问题讨论】:

    标签: python django save


    【解决方案1】:

    最好的方法是使用 django 信号 https://docs.djangoproject.com/es/1.10/ref/signals/

    当你的模型调用方法save()时,你会调用方法change_status

    from django.db.models.signals import pre_save
    
    def change_status(sender, instance, **kwargs):
        # instance object is the model that you have called the method save
        a = A.objects.get(id=instance.id) # or B or C model
        if instance.enable:
            a.enable = False
            # my code.....
    
    pre_save.connect(change_status, sender=A) 
    # sender is the model that will be called every time you call the method save
    

    就是这样 请记住,对象实例在更改之前是您的模型,所以 如果您有a.enable=True 并在change_status 信号中调用save() 方法,您可以在不更改a.enable=True 的情况下进行查询 intance.enable >> True, a.enable >> False 因为 a 还没有保存。

    【讨论】:

    • 是的,这是捕获更改的另一种方式,但在保存对象时仍需要查询对象。
    • 不使用 django 信号,您将仅在一个函数(在此信号中)中实现方法 chage_status(在这种情况下),每当您执行 A.save() 时,这将调用该函数,并且您不必在每种情况下都做相同的过程,你会改变状态,方法做这个过程就是这样,你有什么不明白的?或者谁不明白是我?
    【解决方案2】:

    简而言之——不。但是你可以手动重载 save 方法。

    class B(models.Model):
    
        ...
    
        def save(self, *args, **kwargs):
            if self.pk is not None:
                original = B.objects.get(pk=self.pk)
                if original.enabled != self.enabled:
                    C.enabled = self.enabled
                    C.save()
                    D.enabled = self.enabled
                    D.save()
            super(B, self).save(*args, **kwargs)
    

     

    【讨论】:

    • 嗯。我知道这是一种方法,但是每次保存模型时都需要执行查询。我发现这篇文章与这个主题相关。 stackoverflow.com/questions/23361057/…。我认为在 ModelForm 级别实现此逻辑会比在 Model 级别执行此操作更好。无论如何,谢谢你的回答。
    • 在一个事务中执行它,它将在一个事务中执行所有查询。没有错。
    猜你喜欢
    • 2019-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    相关资源
    最近更新 更多