見出し画像

Django_[transaction.atomic]を使って一連の処理をトランザクション化 #219日目

トランザクションとは、連続した複数のデータベース操作を一つにまとめたものです。処理が最後まで完了したらレコードの登録・変更・削除をまとめてデータベースに反映(コミット)し、エラー等で途中で失敗した場合はその途中までの処理は全て無かったことにしてくれます(ロールバック)。

ちなみにDjangoのデフォルトはトランザクションではなく、オートコミットというモードです。これはsave()やdelete()などの処理が行われると即座にデータベースに反映されるものです。

このオートコミットモードでエラーが発生すると、既にデータベースがコミットされているため、いちいち手動ロールバックをしなければいけません(プログラムで明示的に後始末処理をする)。

https://akiyoko.hatenablog.jp/entry/2020/12/03/081532

これだと大変なので、エラーが起きたら自動でロールバックするような仕組みを導入しておきます。そのための設定がトランザクションです。

https://akiyoko.hatenablog.jp/entry/2020/12/03/081532


Djangoではこのトランザクションの設定方法が2つあります。

  • ATOMIC_REQUESTS:ビュー全体のDB操作が一括でトランザクション化

  • transaction.atomic():任意の箇所をトランザクション化

それぞれ見てみたいと思います。


ATOMIC_REQUESTSの設定方法

これはすごくシンプルで、設定ファイルの「DATABASES」の「ATOMIC_REQUESTS」をTrueにするだけです。

[config/settings.py]

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mysite',
        'USER': 'mysiteuser',
        'PASSWORD': 'mysiteuserpass',
        'HOST': 'localhost',
        'PORT': '5432',
        'ATOMIC_REQUESTS': True,  # 追加
    }
}

これだけで、ビューの開始から終了までのデータベース操作が一つのトランザクションで囲まれます。


transaction.atomic()の設定方法

こちらはwith句を使ってトランザクションの適用範囲を自由に設定できます。with句については以前の記事をぜひご参照ください。

例えば以下のように記述できます。

from . import models

with transaction.atomic():
    sample_update: [models.SampleModel] = []
    sample_model: models.SampleModel = models.SampleModel()
    sanple_model.name = "サンプル"
    sample_model.cost = 123456
    sample_model.active = True
    sample_update.append(sample_model)
    models.SampleModel.objects.bulk_create(sample_update)

上記の処理の途中でエラーが起きた場合、データベースへの変更は行われずにロールバックされます(そもそもbulk_createしているのでDBの更新は一回のみですが)。

ここまでお読みいただきありがとうございました!


参考


この記事が気に入ったらサポートをしてみませんか?