Skip to content

Instantly share code, notes, and snippets.

@AndrewIngram
Last active December 12, 2020 09:10
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AndrewIngram/a37842abd220e5e998525953b9510179 to your computer and use it in GitHub Desktop.
Save AndrewIngram/a37842abd220e5e998525953b9510179 to your computer and use it in GitHub Desktop.
Django one-off on_save callbacks
from django.db import transaction
from django.db import models
from django.db.models.signals import post_save
def on_save(obj: models.Model, callback, on_commit=False):
"""
Attaches a one-off callback that's triggered after a Django model instance is
saved. Optionally makes use of transaction.on_commit to defer until any wrapping
transaction has also committed.
This lets us build up a queue of side-effects to get triggered after some changes
are saved to the database, but crucially in a way such that the side-effects aren't
triggered if the save fails for some reason.
Usage:
on_save(my_instance, lambda: track_event('Something happened'))
on_save(my_instance, lambda: track_event('Something happened'), on_commit=True)
"""
def receiver(sender, instance, using, **kwargs):
if instance == obj:
if on_commit:
transaction.on_commit(callback, using=using)
else:
callback()
post_save.disconnect(receiver)
post_save.connect(receiver, sender=type(obj))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment