I’d sort of seen it around but didn’t understand it, so I looked into it a bit. Please point out anything I’ve gotten wrong.
TL;DR
To put it briefly, by using transaction.atomic you can roll back changes to the DB when an error occurs partway through the processing.
About transaction.atomic
Let me explain with the common bank example: suppose I write code to move money between accounts. (You should never write code like this in production ())
def money_idou():
meron_kouza = Kouza.objects.get(name="meron")
itigo_kouza = Kouza.objects.get(name="itigo")
# Move 150 yen from the `melon account` to the `strawberry account`
itigo_kouza.amount = itigo_kouza.amount - 150
itigo_kouza.save()
meron_kouza.amount = meron_kouza.amount + 150
meron_kouza.save()
Suppose there’s a Kouza (account) model that has name (account name) and amount (balance).
I moved money by adding 150 yen to the melon account and subtracting 150 yen from the strawberry account.
If some kind of error occurs while moving the money, it could happen that the processing ends after the amount has been subtracted from the strawberry account but before it’s added to the melon account.
transaction.atomic is what lets you undo the subtraction from the strawberry account when an error occurs.
Using transaction.atomic
from django.db import transaction
# here
+@transaction.atomic()
def money_idou():
meron_kouza = Kouza.objects.get(name="meron")
itigo_kouza = Kouza.objects.get(name="itigo")
# Move 150 yen from the `melon account` to the `strawberry account`
itigo_kouza.amount = itigo_kouza.amount - 150
itigo_kouza.save()
meron_kouza.amount = meron_kouza.amount + 150
meron_kouza.save()
If you attach @transaction.atomic() as a decorator on a function, the transaction applies across the entire function.
To use it partially, write it as follows.
from django.db import transaction
# here
-@transaction.atomic()
def money_idou():
meron_kouza = Kouza.objects.get(name="meron")
itigo_kouza = Kouza.objects.get(name="itigo")
# Move 150 yen from the `melon account` to the `strawberry account`
+ with transaction.atomic():
+ itigo_kouza.amount = itigo_kouza.amount - 150
+ itigo_kouza.save()
+ meron_kouza.amount = meron_kouza.amount + 150
+ meron_kouza.save()
Summary
By using transaction.atomic, you can roll back changes to the DB when an error occurs partway through the processing.