Overview
このガイドでは、Diango MongoDBバックエンドを使用してトランザクションを実行する方法を学習できます。トランザクションを使用すると、トランザクション全体がコミットされた場合にのみデータを変更する一連の操作を実行できます。トランザクション内のいずれかの操作が成功しない場合、Diango MongoDBバックエンドはトランザクションを停止し、変更が反映される前にデータに対するすべての変更を破棄します。この特徴は アトミック性と 呼ばれます。
MongoDBでは、トランザクションは論理セッション内で実行されます。セッションは 、順番に実行されるよう関連付けられた読み取り操作または書き込み操作のグループです。セッションにより、一連の操作に対する 因果整合性 が有効になり、ACID準拠のトランザクション内で操作を実行できるようになります。これは、アトミック性、整合性、分離、 耐久性 の期待を満たすトランザクションです。
Dlango のネイティブ トランザクションAPI はサポートされていませんが、Diango MongoDBバックエンドは同じ機能を有効にするカスタム トランザクションAPIを提供します。トランザクション内で操作を実行するには、コードのアトミック ブロック内で操作を定義します。Dlango MongoDBバックエンドはセッション ロジックを内部的に管理するため、トランザクションを実行中前にセッションを手動で開始する必要はありません。
重要
トランザクションの制限
Diango MongoDBバックエンドのトランザクションAPI にはいくつかの制限があります。制限のリストを表示するには、 Dpango とMongoDB機能の互換性ガイドの データベースとコレクションのサポート を参照してください。
サンプル データ
このガイドの例では、 Atlasサンプルデータセット の sample_mflix.movies
コレクションを表す Movie
モデルを使用します。Movie
モデルクラスには、次の定義があります。
from django.db import models from django_mongodb_backend.fields import ArrayField class Movie(models.Model): title = models.CharField(max_length=200) plot = models.TextField(blank=True) runtime = models.IntegerField(default=0) released = models.DateTimeField("release date", null=True, blank=True) genres = ArrayField(models.CharField(max_length=100), null=True, blank=True) class Meta: db_table = "movies" managed = False def __str__(self): return self.title
Movie
モデルには、モデルメタデータを指定する内部 Meta
クラスと、モデルの string 表現を定義する __str__()
メソッドが含まれています。 これらのモデル機能の詳細については、「 モデルの作成ガイドの モデルの定義 」を参照してください。
コード例の実行
Pythonインタラクティブシェル を使用してコード例を実行できます。 シェルを入力するには、プロジェクトの ルートディレクトリから次のコマンドを実行します。
python manage.py shell
Python シェルを入力したら、次のモデルとモジュールをインポートしていることを確認します。
from <your application name>.models import Movie from django.utils import timezone from datetime import datetime
Movie
モデルとPython対話型シェル を使用してMongoDBドキュメントを操作する Dlangoアプリケーションを作成する方法については、使い始める チュートリアルをご覧ください。
トランザクションを開始する
データベーストランザクションを開始するには、django_mongodb_backend.transaction.atomic()
関数を呼び出します。この関数は、修飾子またはコンテキスト マネージャーとして使用できます。
次のインポート ステートメントを使用して、transaction
モジュールを必ずインポートしてください。
from django_mongodb_backend import transaction
修飾子の使用
関数の上に @transaction.atomic
修飾子を追加することで、データベーストランザクションを開始できます。この修飾子は、 関数内のすべてのデータベース操作のアトミック性を保証します。関数が正常に完了すると、変更はMongoDBにコミットされます。
次の例では、トランザクション内で create()
メソッドを呼び出します。このメソッドは、トランザクションが成功した場合に sample_mflix.movies
コレクションにドキュメントを挿入します。
def insert_movie_transaction(): Movie.objects.create( title="Poor Things", runtime=141, genres=["Comedy", "Romance"] )
コンテキスト マネージャーの使用
あるいは、transaction.atomic()
コンテキスト マネージャーを使用してアトミック ブロックのコードを作成することもできます。この例では、前の例と同じ操作を実行しますが、トランザクションを開始するためにコンテキスト マネージャーを使用します。
def insert_movie_transaction(): with transaction.atomic(): Movie.objects.create( title="Poor Things", runtime=141, genres=["Comedy", "Romance"] )
トランザクション後にコールバックを実行する
トランザクションが正常に完了した場合にのみ特定のアクションを実行するには、transaction.on_commit()
関数を使用できます。この関数を使用すると、トランザクションがデータベースにコミットされた後に実行されるコールバックを登録できます。関数または任意の 呼び出し可能なオブジェクトを on_commit()
の引数として渡します。
次の例では、関連するデータベーストランザクションが完了した後にのみ genre
値が ["Horror", "Comedy"]
となる映画をクエリします。
def get_horror_comedies(): movies = Movie.objects.filter(genres=["Horror", "Comedy"]) for m in movies: print(f"Title: {m.title}, runtime: {m.runtime}") def insert_movie_with_callback(): with transaction.atomic(): Movie.objects.create( title="The Substance", runtime=140, genres=["Horror", "Comedy"] ) transaction.on_commit(get_horror_comedies)
トランザクションエラーの処理
トランザクション中に発生する例外を処理するには、 アトミック コード ブロックの周囲にエラー処理ロジックを追加します。アトミック ブロック内でエラーを処理すると、Diango からこれらのエラーがぼかして表示される可能性があります。Dlango はトランザクションをコミットするかロールバックするかを決定するためにエラーを使用するため、これにより予期しない動作が発生する可能性があります。
トランザクションが成功しない場合、Diango はモデルのフィールドに加えられた変更を元に戻し ません 。モデルとデータベースドキュメント間の不整合を回避するには、元のフィールド値を手動で復元する必要がある場合があります。
例
次の例には、データベーストランザクションが失敗した場合に、検索されたドキュメントの変更された title
値を元に戻すエラー処理ロジックが含まれています。
movie = Movie.objects.get(title="Jurassic Park") movie.title = "Jurassic Park I" try: with transaction.atomic(): movie.save() except DatabaseError: movie.title = "Jurassic Park" if movie.title == "Jurassic Park I": movie.plot = "An industrialist invites experts to visit his theme park of cloned dinosaurs. After a power failure," \ " the creatures run loose, putting everyone's lives, including his grandchildren's, in danger." movie.save()
コードはモデルの title
値に基づいて 2 番目のデータベース操作を実行するため、トランザクション エラーが発生した場合に変更を元に戻すことで、データの不整合がこれ以上発生するのを防ぎます。
詳細情報
Diango transaction APIの詳細については、Dpango ドキュメントの「 データベーストランザクション 」を参照してください。