django 信号断开不工作
django signal disconnect not working
我有一个信号class,我在其中定义了信号接收器
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
,每次都是 returns False。我做错了什么?
我认为取消注册不起作用的原因是您正在使用属于信号处理器实例的函数。因此它们对于您的 class 的每个实例都是唯一的。我假设(尚未检查)Django 的信号系统通过使用所述函数的哈希来跟踪已注册的函数。因此,当您第二次实例化您的 class 以注销相同的功能时,它们有一个新的散列并且无法被 django 的信号系统找到。
我相信有很多方法可以解决这个问题,但基本思路是确保您使用相同的引用函数调用 connect
和 disconnect
。我已经包含了一个如何做到这一点的小样本。不要认为这是理所当然的,因为我刚刚做了一些小测试来验证它是否有效。
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]
我有一个信号class,我在其中定义了信号接收器
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
,每次都是 returns False。我做错了什么?
我认为取消注册不起作用的原因是您正在使用属于信号处理器实例的函数。因此它们对于您的 class 的每个实例都是唯一的。我假设(尚未检查)Django 的信号系统通过使用所述函数的哈希来跟踪已注册的函数。因此,当您第二次实例化您的 class 以注销相同的功能时,它们有一个新的散列并且无法被 django 的信号系统找到。
我相信有很多方法可以解决这个问题,但基本思路是确保您使用相同的引用函数调用 connect
和 disconnect
。我已经包含了一个如何做到这一点的小样本。不要认为这是理所当然的,因为我刚刚做了一些小测试来验证它是否有效。
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]