Search code examples
djangodjango-modelsdjango-viewsdjango-signals

run some python function whenever a model is created or updated in django?


I want to run some code after my model is saved. Three places to do this will be

1) override save method:

def save(self, *args, **kwargs):
        super(Blog, self).save(*args, **kwargs) 
        do_something()

2) use post_save signal:

def model_created(sender, **kwargs)
    the_instance = kwargs['instance']
    if kwargs['created']:
        do_something()

post_save.connect(model_created, sender=YourModel)

3) do this in the view itself.

if form.is_valid():
   do_something()
   return redirect(reverse("homepage"))

All three should work. This post advocates the second one.

My question is that the second method (post_save) works when the model is first created. I want to call do_something() whenever a new model is created and also when an existing model is updated. In the latter case, I will have kwargs[created] to be false. how do I handle this situation?

P.S: I am currently doing the third one which works fine for both updateView and CreateView. but the problem is it takes time to return from the do_something() function before it is being redirected.


Solution

  • post_save signal is the cleanest option among these three.

    Just eliminate if kwargs['created'] and call do_something() right in the body of a function:

    def model_created_or_updated(sender, **kwargs):
        the_instance = kwargs['instance']
        do_something()
    
    post_save.connect(model_created_or_updated, sender=YourModel)
    

    Now, every time YourModel is created or updated do_something() would be called.

    FYI, created is just a flag that indicates whether YourModel was created (value is True) or updated (value is False).

    Note that do_something() will be executed synchronously and will be "blocking" until done. If you want to execute do_something asynchronously, you need to go with a real task management tool, like celery package.