Отключение сигнала 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. Что я делаю не так?


person Jiyda Moussa    schedule 13.02.2016    source источник
comment
не может реально оценить, что происходит; вы показываете только небольшой фрагмент кода, где вы вызываете разъединение. Нам нужно гораздо больше, чтобы на самом деле выяснить, что не происходит. Если код слишком большой, возможно, выложите его на github и прикрепите ссылку здесь...   -  person Pandrei    schedule 17.02.2016
comment
Похоже, попытка придумать минимально воспроизводимый пример очень поможет вам найти проблему.   -  person Djizeus    schedule 17.02.2016


Ответы (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]
person Johan Rohlén    schedule 18.02.2016