Search code examples
pythondjangodjango-signals

Django Signal.disconnect raises 'function' object has no attribute 'lock' error


I have a function that is the receiver of signals from all models of the system. I want the signals to be interrupted when I am making an database dump population through a Django command, so it wouldn't be invoked when model instances are created by this mean.

This is my receiver function:

@receiver(post_save)
def trigger_payment(sender, instance=None, created=False, **kwargs):
    from TreasuryManagementApp.models import PaymentApplicationTrigger

    if instance.__class__.__name__ not in trigger_models:
        return

    strategies = EventStrategies()

    application_triggers = PaymentApplicationTrigger.objects.filter(event_name__in=trigger_models[instance.__class__.__name__]['event_names'])
    for application_trigger in application_triggers:
        strategies.execute(application_trigger, instance)

And this is the code of my command where I attempt to disconnect the function from signals:

class Command(BaseCommand):
    help = _("""Run this command to import partners and operators from plane files""")

    def execute(self, *args, **kwargs):
        from TreasuryManagementApp.controllers import trigger_payment

        Signal.disconnect(trigger_payment)
        self.import_partners()
        self.import_operators()
        self.import_dead_ones()

The problem is that this call to Signals.disconnect() raises the following exception:

Traceback (most recent call last):

  File "manage.py", line 15, in <module>
    execute_from_command_line(sys.argv)
  File "/Users/hugovillalobos/Documents/Code/TaxistasProject/TaxistasVenv/lib/python3.7/site-packages/django/core/managemen
t/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/Users/hugovillalobos/Documents/Code/TaxistasProject/TaxistasVenv/lib/python3.7/site-packages/django/core/managemen
t/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Users/hugovillalobos/Documents/Code/TaxistasProject/TaxistasVenv/lib/python3.7/site-packages/django/core/managemen
t/base.py", line 316, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Users/hugovillalobos/Documents/Code/TaxistasProject/taxistas/GeneralApp/management/commands/startdatabase.py", lin
e 21, in execute
    call_command('import_people')
  File "/Users/hugovillalobos/Documents/Code/TaxistasProject/TaxistasVenv/lib/python3.7/site-packages/django/core/managemen
t/__init__.py", line 148, in call_command
    return command.execute(*args, **defaults)
  File "/Users/hugovillalobos/Documents/Code/TaxistasProject/taxistas/GeneralApp/management/commands/import_people.py", lin
e 433, in execute
    Signal.disconnect(trigger_payment)
  File "/Users/hugovillalobos/Documents/Code/TaxistasProject/TaxistasVenv/lib/python3.7/site-packages/django/dispatch/dispa
tcher.py", line 138, in disconnect
    with self.lock:
AttributeError: 'function' object has no attribute 'lock'

Solution

  • Use post_save instead of Signal. Documentation in here says: "All signals are django.dispatch.Signal instances", thus, you must disconnect or connect your instance, instead of the Signal class.

    from django.db.models.signals import post_save
    
    class Command(BaseCommand):
        help = _("""Run this command to import partners and operators from plane files""")
    
        def execute(self, *args, **kwargs):
            from TreasuryManagementApp.controllers import trigger_payment
    
            post_save.disconnect(trigger_payment)
            self.import_partners()
            self.import_operators()
            self.import_dead_ones()
            post_save.connect(trigger_payment)  # don't forget to reconnect