2016-11-18 59 views
1

Djangoのtransaction.atomicブロック内で次のコードを実行しています。DjangoセーブポイントロールバックでIntegrityエラーをキャッチすると、TransactionManagementErrorが発生します。

@transaction.atomic() 
def test(): 
    a.save() 
    sid = transaction.savepoint() 
    try: 
     b.save() 
     transaction.savepoint_commit(sid) 
    except IntegrityError as e: 
     transaction.savepoint_rollback(sid) 
    c.save() 

このコードは私に次のエラーを与える -

TransactionManagementError 
An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block. 

私は公式ドキュメントから次のリンクをたどっ。 https://docs.djangoproject.com/en/1.10/topics/db/transactions/#s-savepoint-rollback

私はここで何が欠けていますか?

EDIT: - stacktraceを追加しています。

File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/models/manager.py", line 122, in manager_method 
    return getattr(self.get_queryset(), name)(*args, **kwargs) 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/models/query.py", line 401, in create 
    obj.save(force_insert=True, using=self.db) 
    File "/Users/vibhor/Documents/juggernaut/user-persistence-service/books/models/books.py", line 243, in save 
    transaction.savepoint_rollback(sid) 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/transaction.py", line 66, in savepoint_rollback 
    get_connection(using).savepoint_rollback(sid) 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/backends/base/base.py", line 328, in savepoint_rollback 
    self._savepoint_rollback(sid) 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/backends/base/base.py", line 288, in _savepoint_rollback 
    cursor.execute(self.ops.savepoint_rollback_sql(sid)) 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/backends/utils.py", line 79, in execute 
    return super(CursorDebugWrapper, self).execute(sql, params) 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/backends/utils.py", line 59, in execute 
    self.db.validate_no_broken_transaction() 
    File "/Users/vibhor/Documents/juggernaut/user-venv-new/lib/python2.7/site-packages/django/db/backends/base/base.py", line 429, in validate_no_broken_transaction 
    "An error occurred in the current transaction. You can't " 
TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block. 
+0

を確認してくださいあなたのポストに完全なエラー・トレースバックを追加してください!このようにして、どのコマンドが問題を引き起こしたかを知ることができます。 –

答えて

1

私はあなたがマニュアルに記載され、この問題に実行していると思う:

セーブポイントは、部分的にロールバックを実行して、データベース・エラーから回復するために使用することができます。 atomic()ブロック内でこれを実行している場合は、下位レベルで状況を処理したことがわからないため、ブロック全体がロールバックされます。これを防ぐために、あなたはそこに述べたように、あなたはおそらくロールバックされることから、全体アトミックブロックを防ぐためにtransaction.set_rollback(False)をしたい

...以下の機能をロールバック動作を制御することができます。

ここで手動で行う理由はありますか?コードは、ネストされたアトミック・ブロックと同じことを達成することができ掲示、およびドキュメントノートとして:

atomic()デコレータが入れ子になっている

は、それが部分的にコミットまたはロールバックできるようにセーブポイントを作成します。下記の機能ではなく、atomic()を使用することを強くお勧めします。

1

としてはdocumentationで説明:

原子性を保証するために、原子は、いくつかのAPIを無効にします。アトミック・ブロック内のデータベース接続の自動コミット状態をコミット、ロールバック、または変更しようとすると、例外が発生します。

あなたが欲しいものを達成するための適切な方法は、別のatomicブロックを作成することです:

@transaction.atomic() 
def test(): 
    a.save() 
    try: 
     with transaction.atomic(): 
      b.save() 
    except IntegrityError: 
     #handle exception here... 
     ... 
    c.save() 
-1
@transaction.atomic() 
def test(): 
    a.save() 
    sid = transaction.savepoint() 
    try: 
     with transaction.atomic(): 
      b.save() 
      transaction.savepoint_commit(sid) 
    except IntegrityError as e: 
     transaction.savepoint_rollback(sid) 
    c.save() 

この

関連する問題