2013-08-28 25 views
5

比方說,我有一個獨特的領域電子郵件的模型:Django的潔淨間的鎖定()和save()

class MyModel: 

    email = models.EmailField(unique=True) 

    def save(self): 
     .... # save model 

    def clean(self): 
     .... # validate model, make sure email doesn't already exist. 

通常,如果瀏覽器提交表單的電子郵件是一個已存在的值,它會由於模型表單字段驗證,引發ValidationError。

如果兩個瀏覽器同時提交相同的電子郵件,並且電子郵件是一個尚不存在的值,則至少有一個請求會通過將一行保存到數據庫中而成功。另一個請求,如果它在第一個請求之後到達足夠長的時間,將會被正常處理 - 引發一個ValidationError表示電子郵件已經存在。但是,如果幾乎與第一個請求同時到達,則clean()將成功 - 電子郵件尚不存在,但在執行save()方法時,第一個請求的行將被保存。在後一種情況下,將會引發IntegrityError,而服務器將返回內部服務器500錯誤,這是不可取的。

如何防止這最後一種情況?數據庫事務?

回答

2

只是在這種情況下使用django數據庫事務是不夠的。創建新模型時要執行的操作是將數據庫表鎖與事務一起使用。但是django還沒有鎖定表的API,因此您必須使用原始SQL爲您的數據庫執行表鎖定類型。

這裏如果你使用PostgreSQL是一個很好的例子: http://www.caktusgroup.com/blog/2009/05/26/explicit-table-locking-with-postgresql-and-django/

如果你是在一些其他數據庫,那麼你將要調查如何執行表鎖。

乾杯!如果您覺得這有幫助,請不要忘記對此答案進行投票表決)

1

雖然用例略有不同,但您可能需要閱讀Alex Martelli提供的關於「樂觀併發」方法的this old answer