2012-01-09 45 views
3

我創建了一個Django/Tastypie應用程序,其中多個人可能在同一時間更改數據庫中某一行的屬性,或者可能是過時的PUT數據。是否有一種確保一次只有一個用戶使用REST + HTTP更改對象的正確方法?

例如:

# the Django model 
class Thing(models.Model): 
     name = models.CharField(max_length=100) 
     description = models.TextField() 

# the Tastypie Resource 
class ThingResource(ModelResource): 
     class Meta: 
      queryset = Thing.objects.all() 

現在讓我們說任何數量的用戶可以在任何時間點改變Thingnamedescription。他們可以同時做到這一點,或者有人可以將應用程序長時間開放,然後再回來改變它。

我想避免的是潛在的變化是不正確的。考慮以下情況:

#1 User 1: Opens app viewing Thing #1 with name = "my name", description = "my description" 
#2 User 2: Opens app viewing Thing #1 (same state as User 1) 
#3 User 2: Changes description of Thing #1 to "something" 
#4 User 1: Changes name of Thing #1 to "some other name" 

#4後,事情#1的狀態應該是name = "some other name", description = "something",而不是name = "some other name", description = "my description"

假設應用程序在服務器上的對象發生變化之前不知道(實時或通過定期更新頁面上的數據),如何防止這種情況發生?

我曾考慮添加一個字段sequence = models.PositiveIntegerField(),每次更新時我都會增加一個字段,所以我可以告訴對象是否在更新發生時過時,但這是最好的方法嗎?有沒有更好的辦法?這似乎是一種常見的模式,對嗎?

+1

保留版本號是一個被廣泛接受的良好做法。你當然應該在後端使用某種事務數據庫,否則沒有這樣的方案可以確保正確的行爲。 – Pointy 2012-01-09 22:11:42

+0

是的,我正在使用PostgreSQL。感謝您指出,雖然 – dlamotte 2012-01-10 14:22:48

回答

3

執行此操作的REST式方法是讓客戶端跟蹤隨資源返回的Last-Modified標頭或Etag標頭。然後,當它的帖子,添加頁眉像

If-Unmodified-Since: <date-noted-from-initial-GET> 

If-Match: <etag-noted-from-initial-GET> 

如果資源已被修改,在服務器上,因爲客戶端最初下載它,那麼服務器應該返回失敗的一個「前提條件「迴應。客戶端然後可以檢索當前版本並顯示對用戶合理的內容。

讓tastypie對這些標題做出迴應可能會有點困難。

+0

非常有趣。我很久以前就讀過Etags,但現在我明白他們應該如何工作。你說得對,讓這些品牌適當地迴應這些事情會有很多工作要做,我不確定我會爲此做好準備。感謝你的回答。 – dlamotte 2012-01-10 14:40:03

4

在REST中,資源的狀態由服務器管理,所以您對序列字段的想法是獨一無二的。服務器會跟蹤資源所在的版本,並且客戶端會在發送新版本時說明它認爲創建了哪個版本。如果客戶錯了,服務器就會這麼說。

Ian’s suggestion of ETags or modified dates聽起來像是這樣做的正確方法,並this answer to a similar question同意。我自己實際上並沒有太多的經驗。

+0

我upvoted確認我的方法將工作。感謝您鏈接其他答案,非常豐富。 – dlamotte 2012-01-10 14:40:38

+0

@diamotte:你非常歡迎,我認爲關於ETags可能只是版本號(而不是內容哈希值)的那一點非常有趣。 – 2012-01-10 17:09:59

相關問題