2013-04-13 50 views
1

我有這樣的模式:Django Tastypie使用PATCH或PUT請求進行多對多(自)字段更新?

class UserSub(models.Model): 
    user = models.OneToOneField(User, related_name='userSub') 
    amigos = models.ManyToManyField('self', null=True) 
    title = models.TextField() 

進口的Django用戶模型。

而以下資源:

class UserResource(ModelResource): 
    usersub = fields.OneToOneField('test.api.UserSubResource', attribute = 'personal', related_name='user', full=True, null=True)  
    class Meta: 
     object_class = User 
     fields = ['username', 'first_name', 'last_name', 'password', 'email'] 
     detail_allowed_methods = ['get', 'post', 'put'] 
     authentication = Authentication() 
     authorization = Authorization() 
     queryset = User.objects.all() 
     resource_name = 'users' 
     excludes = ['id'] 

class UserSubResource(ModelResource): 
    user = fields.OneToOneField('test.api.UserResource', attribute = 'user', related_name = 'userSub') 
    amigos= fields.ToManyField('test.api.UserSubResource', attribute = 'amigos', null=True)  
    class Meta: 
     object_class = UserSub 
     fields = ['title'] 
     detail_allowed_methods = ['get', 'post', 'put', 'patch'] 
     authentication = Authentication() 
     authorization = Authorization() 
     always_return_data = True 
     queryset = UserSub.objects.all() 
     resource_name = 'usersub' 
     excludes = ['id'] 

我想吾友特定用戶的值更新。我的數據是:

usersub_json: {"amigos":["/api/v1/usersub/9/","/api/v1/usersub/8/"]} 

$.ajax({ 
     url : 'http://127.0.0.1:8000' + usersub_uri, 
         type : 'PUT', 
         contentType : 'application/json', 
         data : usersub_json, 
         dataType : 'json', 
         processData : false, 
         error : function(http) { 
          if (http.responseText != "") { 
           alert(http.responseText); 
          } 
         } 
        }) 

我得到「202接受」從PUT請求,並且不更新吾友。

和「202接受」來自PATCH請求,並且amigos不更新。

如果我在創建usersub時在第一個發佈請求中添加了amigos,它會成功將它們添加到數據庫中。但如果使用PUT或PATCH將更多數據添加到陣列,則不會更新。

+0

您是否遇到此實際代碼的問題?或者這只是一個人爲的例子?在你的例子中有幾件事情,我認爲它會在這種情況下實際工作:1)你直接修補UserSubResource而不是UserResource。 2)我認爲這個問題與嵌套的M2M在資源中多次出現有關,但您的示例只有一個相關的ToManyField。我正在處理同樣的問題並尋找解決方案。 – kball

回答

2

我不能確定它是否與您的情況相同,但我發現我的問題。

讓我修改您的例子稍微反映我所遇到的情況:

class UserResource(ModelResource): 
    usersubs = fields.ToManyField('test.api.UserSubResource', attribute = 'usersubs', full=True, null=True) 
    specialUsersub = fields.ToOneField('test.api.UserSubResource', attribute = 'special_user_sub', full=True, null=True) 
    class Meta: 
     object_class = User 
     fields = ['username', 'first_name', 'last_name', 'password', 'email'] 
     detail_allowed_methods = ['get', 'post', 'put'] 
     authentication = Authentication() 
     authorization = Authorization() 
     queryset = User.objects.all() 
     resource_name = 'users' 
     excludes = ['id'] 

class UserSubResource(ModelResource): 
    amigos= fields.ToManyField('test.api.UserSubResource', attribute = 'amigos', null=True)  
    class Meta: 
     object_class = UserSub 
     fields = ['title'] 
     detail_allowed_methods = ['get', 'post', 'put', 'patch'] 
     authentication = Authentication() 
     authorization = Authorization() 
     always_return_data = True 
     queryset = UserSub.objects.all() 
     resource_name = 'usersub' 
     excludes = ['id'] 

和要求:

PATCH /users/1/ 
{ "specialusersub" : { "id" : 3, "amigos" : ["/api/v1/usersub/9/","/api/v1/usersub/8/"] } } 

在我的情況下,這個問題是由試圖修補嵌套一個一對多的資源而導致的父級資源還存在於頂級的ToMany關係中時深兩級。因爲因爲在資源領域的秩序的嵌套的,操作的順序發生這樣的:

  1. 水合物usersubs成束(及其嵌套關係 - 從數據庫加載,在我們的例子空)
  2. 水合物specialUsersub成束(及其嵌套關係 - 包括在請求數據)
  3. 保存specialUsersub(嵌套資源在這裏正確保存)
  4. [此時tastypie應檢查是否有其水合資源進行保存,並補充水分適當件的捆綁但它沒有,所以:]
  5. 保存usersubs(如果specialUsersub的資源也存在於usersubs當時被以前保存將在usersubs在步驟1中水合載入的陳舊數據覆蓋)

爲了更加精確,因爲tastypie故意清除所有m2m關係,然後用存儲在包中的內容重新填充它們,過時的數據會破壞新數據,在3中創建的amig將被刪除並替換爲在1中加載的[]空列表。

我還在測試,但我認爲解決的辦法/黑客是確保您有更新的嵌套資源徘徊無論您tastypie資源可能期待它:

PATCH /users/1/ 
{ "usersubs" : [{ "id" : 3, "amigos" : ["/api/v1/usersub/9/","/api/v1/usersub/8/"] }], "specialusersub" : { "id" : 3, "amigos" : ["/api/v1/usersub/9/","/api/v1/usersub/8/"] } } 

顯然,這並不理想。如果我想出一個更合適的解決方案,我會告訴你。

相關問題