📄

Django transaction.atomicについて

この記事は公開から2年以上経過しています。内容が古くなっている可能性があります。

なんかみたことはあるけど理解していなかったため、ちょっと調べました。 間違っていたらご指摘ください。

TL;DR

短い文で表すと、transaction.atomicを使うことで処理の途中でエラーが起きた時DBの変更が戻すことができる。

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()

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の変更をロールバックすることができる。

参考

新着記事

関連ネットワーク(beta)

ドラッグで移動 / Ctrl+ホイールでズーム