8

TL;DR:
I need a way to trigger a custom signal after the post_save signal, automatically, is there any way of doing it?


I'm currently developing a library for django that requires a lot of comes and goes with the post_save signal in django and I was wondering if it's possible to trigger another signal after the post_save so I could implement my own and not intervene the post_save in case a project that uses the library needs to do it.

So far I know that signals are expected to receive a class as a sender argument, and if I trigger manually the signal from the post_save I would be doing nothing (I'd still be intervening it). Is there any workaround for this? Am I missing something in the docs?

John Moutafis
  • 22,254
  • 11
  • 68
  • 112
CastleDweller
  • 8,204
  • 13
  • 49
  • 69
  • *Why* do you need a custom signal? If what you need to do happens every time something is saved, then just use the `post_save` signal. It doesn't matter whether or not you use all the arguments that are passed to the signal handler. – solarissmoke Dec 16 '17 at 02:39
  • Hey, @OscarCarballal I was wondering, did you find my answer helpful? – John Moutafis Dec 22 '17 at 16:55
  • Yes, sorry, I completely forgot about marking it. Thanks :) – CastleDweller Jan 04 '18 at 14:46

1 Answers1

6

Although this may be possible by calling a signal manually from inside another signal like this:

post_save.send(MyModel, instance=a_mymodel_instance)

There are easier ways to do something like that:

Let us assume that you follow the file organization that I use in this answer: Django Create and Save Many instances of model when another object are created


Suggestion 1:

  • Let us assume that your first post_save does something to MyModel1 and another post_save signal does something to MyModel2 after some processing on the instance that triggered the first signal.
  • post_save is always send at the end of a save() method.
  • Organize your signals as follows:

    @receiver(post_save, sender=MyModel1)
    def mymodel1_signal (sender, instance, **kwargs):
        Do stuff on MyModel1 instance...
        Do also stuff on MyModel2 and then call MyModel2.save()
    
    
    @receiver(post_save, sender=MyModel2)
    def mymodel2_signal (sender, instance, **kwargs):
        Do stuff on MyModel2 instance...
    

    This way the mymodel2_signal signal will get triggered after the call to MyModel2.save() from mymodel1_signal.


Suggestion 2:

  • Use a mix of signals to achieve the correct "timing".
  • Let us assume that you want to start a process on MyModel2 before a MyModel1 get's saved
  • Use a pre_save and a post_save signal:

    @receiver(pre_save, sender=MyModel1)
    def mymodel1_signal (sender, instance, **kwargs):
        Do stuff on MyModel1 instance...
        Do also stuff on MyModel2 and then call MyModel2.save()
    
    
    @receiver(post_save, sender=MyModel2)
    def mymodel2_signal (sender, instance, **kwargs):
        Do stuff on MyModel2 instance...
    

Suggestion 3:

Use a MyModel2 method directly inside a MyModel1 post_save signal.

John Moutafis
  • 22,254
  • 11
  • 68
  • 112