Using Django signals receiver
decorator I have the following function.
@receiver(post_save)
def action_signal(sender, instance, created, **kwargs):
pass
Is it possible to use the receiver
decorator on a class instead on a function? The reason for this is I would like to have a __init__
method etc.
i.e. How can I get something like this to work...
class ActionSignals
def __init__(self):
self.stuff
@receiver(post_save)
def action_signal(sender, instance, created, **kwargs):
print(self.stuff)
Using the receiver
decorator on a class method doesn't really make sense. When do you expect the object to be instantiated and the __init__
method to run?
You can use the manual method for connecting signals, instead of the receiver
decorator.
First instantiate the object:
action_signal = ActionSignals()
Then you can use the connect
method to connect the signal:
post_save.connect(action_signal.action_signal)
You can do this:
class ActionSignals(object):
def __init__(self, *args, **kwargs):
# ...
def __call__(self, *args, **kwargs):
print(self.stuff)
Then to connect the signal handler:
handler = ActionSignals()
post_save.connect(handler)
This makes use of python's "magic" __call__
method that allows you to use an instance of a class as a function.
Be careful about where you are adding the handlers in your code, as you might create duplicates. For example if you were to put the second bit of code in the module root, it would add a handler every time the module is imported.
To avoid this you can do the following:
post_save.connect(handler, dispatch_uid="my_unique_identifier")
As @Alasdair pointed out, you can add handlers in AppConfig.ready()
(and this is the recommended place to do it), although generally it can be done anywhere if you take care not to create undesired duplicates.
See "Where should this code live?" in this doc.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With