2016-02-13 76 views
2

我有一個信號類,我定義的信號接收器Django的信號斷開不工作

class SearchSignalProcessor(object): 
    def post_save_connector(self, sender, instance, **kwargs): 
     # do something 

    def pre_delete_connector(self, sender, instance, **kwargs): 
     # do something 

    def setup(self, model): 
     signals.post_save.connect(self.post_save_connector, sender=model, dispatch_uid="index_after_save") 
     signals.pre_delete.connect(self.pre_delete_connector, sender=model, dispatch_uid="index_before_delete") 

    def teardown(self, model): 
     signals.pre_delete.disconnect(self.pre_delete_connector, sender=model, dispatch_uid="index_after_save") 
     signals.post_save.disconnect(self.post_save_connector, sender=model, dispatch_uid="index_before_delete") 

我可以成功連接的信號:

signal_processor = SearchSignalProcessor()    
signal_processor.setup(SomeModel) 

disconnect不起作用。我嘗試過並且沒有dispatch_uid,每次只返回False。我究竟做錯了什麼?

+4

不能真正評估發生了什麼;你只會顯示一小段你稱之爲斷開連接的代碼。我們需要更多的東西來真正弄清楚發生了什麼事情。如果代碼太大,可能把它放在github上,並在這裏附上一個鏈接... – Pandrei

+1

聽起來像試圖想出一個[mcve]會幫助你很多發現問題。 – Djizeus

回答

1

我相信取消註冊不起作用的原因是因爲您正在使用屬於您的信號處理器實例的函數。因此,它們對您班級的每個實例都是獨一無二的。我假設(未檢查)Django的信號系統通過使用所述函數的散列來跟蹤已註冊的函數。所以當你第二次實例化你的類以取消註冊相同的函數時,它們會有一個新的哈希,並且不能被django的信號系統找到。

我確定有很多方法可以解決這個問題,但基本思路是確保您使用相同的引用函數調用connectdisconnect。我已經包含了一個小樣本,說明如何做到這一點。不要認爲這是理所當然的,因爲我剛剛做了一些小測試來驗證它是否有效。

class SearchSignalProcessor(object): 

    registry = {} 

    @staticmethod 
    def get_post_save_connector(): 
     def post_save_connector(sender, instance, **kwargs): 
      #Do something 
     return post_save_connector 

    @staticmethod 
    def get_pre_delete_connector(): 
     def pre_delete_connector(sender, instance, **kwargs): 
      # Do something 
     return pre_delete_connector 

    def setup(self, model): 
     if model in self.registry: 
      self.teardown(model) 

     self.registry[model] = { 
      'pre_delete': self.get_pre_delete_connector(), 
      'post_save': self.get_post_save_connector() 
     } 

     signals.post_save.connect(
      self.registry[model]['post_save'], 
      sender=model, 
      dispatch_uid="index_after_save" 
     ) 
     signals.pre_delete.connect(
      self.registry[model]['pre_delete'], 
      sender=model, 
      dispatch_uid="index_before_delete" 
     ) 

    def teardown(self, model): 
     if model in self.registry: 
      signals.pre_delete.disconnect(self.registry[model]['post_save']) 
      signals.post_save.disconnect(self.registry[model]['pre_delete']) 
      del self.registry[model]