2011-01-21 34 views
0

在我的Django應用程序中,我有從數據庫中刪除模型的單個實例的代碼。有兩種併發請求都有可能試圖同時刪除同一個模型。在這種情況下,我希望一個請求成功,另一個請求失敗。我怎樣才能做到這一點?使用事務安全地從數據庫中刪除Django模型

問題是,當使用delete()刪除實例時,Django不會返回有關命令是否成功的任何信息。此代碼說明了這個問題:

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

這兩個delete()命令只有一個真正刪除的對象,但我不知道是哪一個。不會拋出異常,並且不會返回任何內容來指示命令的成功。在純SQL中,該命令將返回刪除的行數,如果該值爲0,我會知道我的刪除失敗。

我正在使用默認的Read Commited隔離級別的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

你可以把約束權到SQL使用的,而不是Model.delete QuerySet.delete DELETE語句:

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

這不會發出SELECT查詢所有,只是沿着線的東西:

DELETE FROM Book WHERE id=1; 

,處理刪除同一記錄在同一時間兩個併發請求的競爭狀態,但它不會讓你知道你是否刪除最先到達那裏。爲此,你必須得到原始光標(其中django lets you do),.execute()上面的DELETE自己,然後拿起光標的rowcount屬性,如果你沒有結束刪除任何事情,它將是0。

相關問題