我有一个信号类,我在其中定义信号接收器
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。我做错了什么?
答案 0 :(得分:1)
我认为取消注册不起作用的原因是因为您使用属于信号处理器实例的函数。因此,它们对于您班级的每个实例都是唯一的。我假设(没有检查)Django的信号系统通过使用所述函数的散列来跟踪已注册的函数。因此,当你第二次实例化你的类以取消注册相同的函数时,它们会有一个新的哈希值,并且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]