web-dev-qa-db-ja.com

Django-アトミックトランザクションでのロールバック保存

オブジェクトを保存するビューを作成しようとしていますが、例外が発生した場合はndoを保存したいと思います。これは私が試したものです:

class MyView(View):

    @transation.atomic
    def post(self, request, *args, **kwargs):
        try:
            some_object = SomeModel(...)
            some_object.save()

            if something:
                raise exception.NotAcceptable()
                # When the workflow comes into this condition, I think the previous save should be undome
                # Whant am I missing?

        except exception.NotAcceptable, e:
            # do something

私は何を間違えていますか?例外が発生した場合でもsome_objectはまだデータベースにあります。

24
Gocht

原子性ドキュメンテーション

要約する、 @transaction.atomicは、ビューがエラーなしで応答を生成する場合、データベースでトランザクションを実行します。自分で例外をキャッチしているので、Djangoのように見えますが、ビューはうまく実行されたようです。

例外をキャッチした場合は、自分で処理する必要があります。 Controlling Transactions

失敗した場合に適切なJSON応答を生成する必要がある場合:

from Django.db import SomeError, transaction

def viewfunc(request):
    do_something()

    try:
        with transaction.atomic():
            thing_that_might_fail()
    except SomeError:
        handle_exception()

    render_response()
30
jlucier

ただし、transaction.atomicで装飾された関数で例外が発生した場合、何もする必要はありません。 関数を実行する前にデコレータによって作成されたセーブポイントに自動的にロールバックします 、 as 文書化

atomicを使用すると、データベースの原子性が保証されるコードブロックを作成できます。コードブロックが正常に完了すると、変更がデータベースにコミットされます。例外がある場合、変更はロールバックされます。

Exceptブロックで例外がキャッチされた場合、atomicが例外をキャッチしてロールバックを実行するように例外を再生成する必要があります。

    try:
        some_object = SomeModel(...)
        some_object.save()

        if something:
            raise exception.NotAcceptable()
            # When the workflow comes into this condition, I think the previous save should be undome
            # Whant am I missing?

    except exception.NotAcceptable, e:
        # do something
        raise  # re-raise the exception to make transaction.atomic rollback

また、さらに制御したい場合は、手動で 以前に設定されたセーブポイント にロールバックできます。

class MyView(View):
    def post(self, request, *args, **kwargs):
        sid = transaction.savepoint()
        some_object = SomeModel(...)
        some_object.save()

        if something:
            transaction.savepoint_rollback(sid)
        else:
            try:
                # In worst case scenario, this might fail too
                transaction.savepoint_commit(sid)
            except IntegrityError:
                transaction.savepoint_rollback(sid)
14
jpic