django信号断开不工作

时间:2016-02-13 23:09:26

标签: python django django-signals

我有一个信号类,我在其中定义信号接收器

run()

我可以成功连接信号:

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,每次只返回False。我做错了什么?

1 个答案:

答案 0 :(得分: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]