Django transactions
Django documentation about transaction points out:
Django uses transactions or savepoints automatically to guarantee the integrity of ORM operations that require multiple queries, especially
delete()
andupdate()
queries.
This means whenever we call save()
or create()
, it’s already wrapped in
a transaction. And usually new data is not in the database yet when we try to
get that again somewhere after.
To make sure it’s commited, we have to use transaction.on_commit()
.
There are 2 popular cases I find that we must use on_commit()
function.
The first one is when we send task to a Celery queue. The error we usually made
here is to put that on a post_save
signal and hope for the best. Remember that
post_save
is in the same transaction with save()
, so there is no guarantee
that new data will be in the database when Celery task get it from there.
We must use put the task to on_commit()
function like this:
transaction.on_commit(lambda: celery_task_with_id(id))
The second case is when we want to do something after all inline forms in admin page is saved. But the thing we actually want is data is commited to database. You already know how to do it, just like the case above.
The catch here is we can put on_commit()
function in many places, as long as
it’s in the transaction. I usually put that on save_model()
or save_related()
,
depend on what extra infomation I need for further processing.