なんかみたことはあるけど理解していなかったため、ちょっと調べました。
間違っていたらご指摘ください。
TL;DR
短い文で表すと、transaction.atomic
を使うことで処理の途中でエラーが起きた時DBの変更が戻すことができる。
transaction.atomic
について
どういうことかというと、よくある銀行の例で
口座間のお金を移動する処理を書いてみるとする。(本番でこんなコードを書いてはいけない())
sample.py
def money_idou():
meron_kouza = Kouza.objects.get(name="meron")
itigo_kouza = Kouza.objects.get(name="itigo")
# `メロン口座`から`いちご口座`へ150円移動する
itigo_kouza.amount = itigo_kouza.amount - 150
itigo_kouza.save()
meron_kouza.amount = meron_kouza.amount + 150
meron_kouza.save()
name
(口座名)とamount
(残高)を持ったKouza
モデルがあるとする。
メロン口座
は+150円、いちご口座
は-150円することでお金を移動した。
もし、お金の移動中になにかしらのエラーが発生したときいちご口座
から引かれてメロン口座
に加算される前に処理が終わってしまうなんてことが起きてしまう。
エラーが発生したときいちご口座
から引いたものを無かったことにすることができるのがtransaction.atomic
。
transaction.atomic
を使う
from django.db import transaction
#ここ
+@transaction.atomic()
def money_idou():
meron_kouza = Kouza.objects.get(name="meron")
itigo_kouza = Kouza.objects.get(name="itigo")
# `メロン口座`から`いちご口座`へ150円移動する
itigo_kouza.amount = itigo_kouza.amount - 150
itigo_kouza.save()
meron_kouza.amount = meron_kouza.amount + 150
meron_kouza.save()
@transaction.atomic()
を関数のデコレータとしてつけるとその関数全体でトランザクションが効く。
部分的に使用する場合は以下のように記述する。
from django.db import transaction
#ここ
-@transaction.atomic()
def money_idou():
meron_kouza = Kouza.objects.get(name="meron")
itigo_kouza = Kouza.objects.get(name="itigo")
# `メロン口座`から`いちご口座`へ150円移動する
+ with transaction.atomic():
+ itigo_kouza.amount = itigo_kouza.amount - 150
+ itigo_kouza.save()
+ meron_kouza.amount = meron_kouza.amount + 150
+ meron_kouza.save()
まとめ
transaction.atomic
を使うことで処理の途中でエラーが起きたときにDBの変更をロールバックすることができる。