Search code examples
pythondjangodjango-modelsdjango-rest-frameworkdjango-simple-history

Django trigger post_save on update()


So I am using django-simple-history module that tracks changes in Model instances. However, it uses post_save signal to do so. In my project, I also need it to trigger on update().

My question is: How to overwrite the update() method to trigger post_save signals?


Solution

  • The problem you'll have by doing this is that .update() doesn't have to load the objects from the database in order to do its thing. Consider this example on a users table with 1 million rows:

    users = User.objects.filter(date_joined__lte=now() - timedelta(days=30)
    users.update(is_active=False)
    

    What django will do here is not load potentially hundreds of thousands of rows from your database, just to set is_active to False, then save each row individually, but instead issue an UPDATE command via the database engine directly: UPDATE users SET is_active=False WHERE date_joined < 30_DAYS_AGO. This is the sole reason Django does not trigger post_save on update: because it hasn't loaded anything from the database in the first place.

    In order for it to trigger the signal, it would need to load all those objects from the database, issue a database query UPDATE users SET is_active=False WHERE id=X thousands of times, once for each row, then send the signal. Which would kill performance.

    If you really want to use the signal, you will need to load the objects from the database, iterate over them and save them one at a time. There's no way around this unfortunately.