Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I have a Django signal call a model method?

Tags:

Maybe it's just late, but I cannot figure out why this isn't working. When I have a post_save signal call a generic function, it works, but when I have a post_save signal call a method from a model, nothing happens. Here is code that works:

class Revision(models.Model):     # Model junk...  def send_email(sender, instance, created, **kwargs):     if created:         print "DO STUFF"  signals.post_save.connect(send_email, sender=Revision) 

But this does not work:

class Revision(models.Model):     # Model junk...      def send_email(sender, instance, created, **kwargs):         if created:             print "DO STUFF"  signals.post_save.connect(Revision.send_email, sender=Revision) 

Is there a kind soul out there who will keep me from smashing my head into the wall? Thanks.

like image 695
winduptoy Avatar asked Sep 23 '12 05:09

winduptoy


People also ask

How do you call a signal in Django?

There are two ways to send signals in Django. To send a signal, call either Signal. send() (all built-in signals use this) or Signal. send_robust() .

How do I create a signal in Django?

There are 3 types of signal. pre_save/post_save: This signal works before/after the method save(). pre_delete/post_delete: This signal works before after delete a model's instance (method delete()) this signal is thrown.

Where is Pre_save signal in Django?

pre_save. This is sent at the beginning of a model's save() method. Arguments sent with this signal: sender.

What is Post_save in Django?

The post_save logic is just a normal function, the receiver function, but it's connected to a sender, which is the Order model. The code block below demonstrates the sample receiver function as a post-save. 1from django. db. models.


1 Answers

It seems to me that the problem in the second one is you are using an unbounded method send_mail. If you really want to call send_mail from within a class, maybe @classmethod or @staticmethod will help you out:

class Revision(models.Model):     # Model junk...      @classmethod     def send_email(cls, sender, instance, created, **kwargs):         if created:             print "DO STUFF"  signals.post_save.connect(Revision.send_email, sender=Revision) 

or

class Revision(models.Model):     # Model junk...      @staticmethod     def send_email(sender, instance, created, **kwargs):         if created:             print "DO STUFF"  signals.post_save.connect(Revision.send_email, sender=Revision) 

Alternatively without using these decorators, you can pass the bounded instance method:

class Revision(models.Model): # Model junk...      def send_email(self, sender, instance, created, **kwargs):         if created:             print "DO STUFF"  signals.post_save.connect(Revision().send_email, sender=Revision) 

References:

  1. From the Django source code:

    def connect(self, receiver, sender=None, weak=True, dispatch_uid=None):     """     Connect receiver to sender for signal.      Arguments:          receiver             A function or an instance method which is to receive signals.             Receivers must be hashable objects.              If weak is True, then receiver must be weak-referencable (more             precisely saferef.safeRef() must be able to create a reference             to the receiver).              Receivers must be able to accept keyword arguments.              If receivers have a dispatch_uid attribute, the receiver will             not be added if another receiver already exists with that             dispatch_uid. 
  2. Difference between @classmethod and @staticmethod: What is the difference between @staticmethod and @classmethod in Python?

like image 151
K Z Avatar answered Oct 07 '22 17:10

K Z