【问题标题】:django signal disconnect not workingdjango信号断开不起作用
【发布时间】:2016-02-13 23:09:26
【问题描述】:

我有一个定义信号接收器的信号类

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。我做错了什么?

【问题讨论】:

  • 无法真正评估发生了什么;您只在调用断开连接的地方显示一小段代码。我们需要更多才能真正弄清楚发生了什么。如果代码太大,可以把它放在github上并在此处附上链接......
  • 听起来像是想出一个minimal reproducible example 会帮助你找到问题。

标签: python django django-signals


【解决方案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]

【讨论】:

    猜你喜欢
    • 2015-01-22
    • 2021-04-21
    • 2011-09-03
    • 2016-01-28
    • 2018-12-29
    • 1970-01-01
    • 1970-01-01
    • 2015-03-25
    • 2018-06-26
    相关资源
    最近更新 更多