2011-01-21 13 views
0

私のDjangoアプリケーションでは、データベースからモデルの単一インスタンスを削除するコードがあります。同時に2つの同時リクエストが同じモデルを同時に削除しようとする可能性があります。この場合、1つのリクエストを成功させ、もう1つのリクエストを失敗させます。これどうやってするの?トランザクションを使用してデータベースからDjangoモデルを安全に削除する

delete()でインスタンスを削除するとき、Djangoはコマンドが成功したかどうかについての情報を返しません。このコードは、問題を示しています

b0 = Book.objects.get(id=1) 
b1 = Book.objects.get(id=1) 
b0.delete() 
b1.delete() 

一つだけこれら二つのdelete()のコマンドは、実際にオブジェクトを削除したが、私はどちらかわかりません。例外はスローされず、コマンドの成功を示すために何も返されません。純粋なSQLでは、このコマンドは削除された行の数を返します。値が0の場合、削除が失敗したことがわかります。

私はPostgreSQLを既定の読み取りコミットされた分離レベルで使用しています。このレベルの私の理解は、各コマンド(SELECT、DELETEなど)はデータベースのスナップショットを見るが、次のコマンドはデータベースの異なるスナップショットを見ることができるということである。これは私がこのようなことをすることができないことを意味すると信じています:

# I believe this wont work 
@commit_on_success 
def view(request): 
    try: 
    book = Book.objects.get(id=1) 
    # Possibility that the instance is deleted by the other request 
    # before we get to the next delete() 
    book.delete() 
    except ObjectDoesntExist: 
    # Already been deleted 

アイデアはありますか?

答えて

4

かわりModel.deleteのQuerySet.deleteを使用してDELETEステートメントを右SQLに制約を置くことができます。

Book.objects.filter(pk=1).delete() 

これは、全くの線に沿ってだけで何かをSELECTクエリを発行することはありません。同時に同じレコードを削除する2つの同時要求の競合状態を処理しますが、それはあなたがあなたの削除は最初そこに着いたかどうかを知ることはできません

DELETE FROM Book WHERE id=1; 

。そのためには、生のカーソル(django lets you do)を取得し、上記のDELETEを実行してから、カーソルのrowcount属性を取得しなければなりません。何も削除していなければ0になります。

関連する問題