2017-03-03 2 views
0

Djangoのドキュメントを約transaction.atomic()と例外これを言う:例外を処理するためにネストされたDjango transaction.atomic()を使用していますか?

https://docs.djangoproject.com/en/1.10/topics/db/transactions/#django.db.transaction.atomic

は、原子内部の例外をキャッチしないでください!上記のように

...データベースエラーをキャッチする

正しい方法は、アトミック・ブロックの周囲にあります。必要に応じて、この目的のために追加のアトミックブロックを追加します。このパターンには別の利点があります。例外が発生した場合に、どのオペレーションがロールバックされるかを明示的に区切ります。

...

"必要であれば、この目的のための余分なアトミック・ブロックを追加します。" はどのようなのように見える?これを行うことはできますか?これは「予期しない動作」を引き起こしますか?

valid = True 
errors = [] 
objects = MyModel.objects.all() 
try: 
    with transaction.atomic(): 
     for obj in objects: 
      try: 
       # Update and save obj here... 
      except: 
       errors.append("obj {} had errors".format(obj.pk)) 
       valid = False 
     if not valid: 
      raise Exception('batch update failed.') 

except Exception as ex: 
    # Handle it.. 

これは次のように書いていますか?もしそうなら、なぜこれは違うのですか?トランザクションブロックがDatabaseError(またはそのサブクラス)をキャッチした場合にのみ

valid = True 
errors = [] 
objects = MyModel.objects.all() 
try: 
    with transaction.atomic(): 
     for obj in objects: 
      try: 
       with transaction.atomic(): # Here's my 'extra atomic block' 
        # Update and save obj here... 
      except: 
       errors.append("obj {} had errors".format(obj.pk)) 
       valid = False 
     if not valid: 
      raise Exception('batch update failed.') 

except Exception as ex: 
    # Handle it.. 

答えて

1

は、Djangoはrolbackトリガー、だから、その前にそれをキャッチべきではありません。 2番目のトランザクションブロック(2番目の例)を追加すると、エラーがキャッチされ、トランザクションにロールバックがマークされ、必要な処理を実行できます。

私はあなたが良いことをする必要があると思いますが、まったく同じエラーを再発生しますが、これは単なる推測です。

+0

>それを前にキャッチしますか? –

+0

最初の例では、トランザクションブロックが終了する前にエラーをキャッチするので、トランザクションロジックは何かが間違っていることを認識せず、トランザクションをロールバックしません。私はそれが今より理解できることを願っています。 –

+0

トランザクションブロックが_any_例外で終了すると、Djangoはロールバックをトリガします。しかし、 'DatabaseError'は現在のトランザクションの問題を示しているので、その中で(最も内側の)アトミックブロックがロールバックされるまで、' DatabaseError'を捕まえるべきではありません。他の例外の場合、トランザクションをロールバックしたくない場合は、アトムブロック内でそれらを捕捉することができます。 – knbk

関連する問題