Search code examples
djangoselfdjango-signals

Can I use Signal receiver within a class


I have a signal like this:

virtual_daily_created = django.dispatch.Signal(providing_args=['min_date', 'max_date', 'train_id'])

Calling it from a view like this:

signal = virtual_daily_created.send_robust(self.__class__, min_date=start_ts,
                                           max_date=end_ts,
                                           train_id=train_id)

and the receiver is in a class defined like this:

class BigQueryData:
    def __init__(self):
        some_code

    def set_query(self, table: bigquery.TableReference, train_id: str, min_date: datetime, 
max_date: datetime,**kwargs) -> str:
        do_thing

    def set_table(self, type: str) -> bigquery.TableReference:
        do_thing

    @receiver(virtual_daily_created)
    def get_gga_data(self, min_date: datetime, max_date: datetime, train_id: str, **kwargs):
        do_thing

Finally in my app containing the BigQueryData class, in a app.py file I have:

from django.apps import AppConfig
from django.dispatch import receiver


class ShiftsConfig(AppConfig):
  name = 'shifts'

    def ready(self):
        from api.v1.virtual_daily_report import VirtualDailyReportList
        from reports.signals import virtual_daily_created

        virtual_daily_created.connect(receiver, sender=VirtualDailyReportList)

Thing is when a signal is received I got this error:

get_gga_data() missing 1 required positional argument: 'self'

So I tried to change my signal like this:

virtual_daily_created = django.dispatch.Signal(providing_args=['self', 'min_date', 'max_date', 'train_id'])

And to Call it like this:

signal = virtual_daily_created.send_robust(self.__class__, self=BigQueryData(), 
                                           min_date=start_ts,
                                           max_date=end_ts,
                                           train_id=train_id)

But then when I receive a signal I get this error:

send_robust() got multiple values for argument 'self'

Is it even possible to receive a signal from a method with self as first arg ?

Thank you :)


Solution

  • Mark it as a staticmethod or classmethod to be able to call it without the self argument being needed.

        @receiver(virtual_daily_created)
        @staticmethod
        def get_gga_data(min_date: datetime, max_date: datetime, train_id: str, **kwargs):
            do_thing