2017-08-01 116 views
1

当一个字段发生更改时,我需要执行一些操作。使用post_save而不是pre_save信号检测字段更改

由于这个动作需要与已保存对象的工作,我不能用pre_save信号是这样的:

@receiver(pre_save, sender=reservation_models.Reservation) 
def generate_possible_pairs(sender, instance, **kwargs): 
    try: 
     reservation_old = sender.objects.get(pk=instance.pk) 
    except sender.DoesNotExist: 
     pass # Object is new, so field hasn't technically changed, but you may want to do something else here. 
    else: 
     if not reservation_old.datetime == instance.datetime: # Field has changed 
      do_something(instance) # It would be better to be sure instance has been saved 

是否有可能使用post_save信号呢?

我想避免添加临时属性到这个模型。

+0

首先(也是最进口)问题:你为什么要在这里使用的信号? (提示:您可以自定义模型的save()方法)。第二个问题:是什么让你认为你不能将“pre_save”用于“已保存”的对象? 'pre_save'不是'pre_create',每次保存模型实例时都会调用它。 –

+0

1.虽然信号可能导致痛苦的调试,但它似乎是一个更优雅的解决方案。如果我使用覆盖保存方法进行检测,则必须添加多个(6)附加字段。我必须检查两个日期和两个时间属性(日期时间属性),状态以及对象是否已创建。 2.我认为,如果pre_save方法(异常等)发生任何事情,它不会保存到数据库并提交。 –

+0

就我而言,最“优雅”的解决方案是最简单的解决方案。另外我不明白为什么在模型的'save()'中做你的工作需要任何额外的字段 - 你只需要做和pre_save处理程序一样的事情:从db中加载原始版本(在保存任何内容之前)并比较两者版本(可以在保存后完成)。 wrt/point 2 /,我可能误解了你的要求,它应该“与已保存的对象一起工作”:) –

回答

5

使用post_save信号,你将无法从数据库检索前一个状态 - 但为什么要使用信号呢?

class Reservation(models.Model): 
    def save(self, *args, **kw): 
     old = type(self).objects.get(pk=self.pk) if self.pk else None 
     super(Reservation, self).save(*args, **kw) 
     if old and old.datetime != self.datetime: # Field has changed 
      do_something(self) 

您可能还需要阅读此:https://lincolnloop.com/blog/django-anti-patterns-signals/

-1

是的,你也可以使用post_save。你应该记住信号是同步的

+0

如何使用post_save?我不知道如何识别post_save中的变化,因为实例已经保存。 –

+0

pre_save在对象保存之前触发,post_save在对象保存之后触发,因此只需将pre_save更改为post保存在@receiver修饰器中 – phacic