2017-08-01 99 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