2013-04-13 49 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/"] } } 

显然,这并不理想。如果我想出一个更合适的解决方案,我会告诉你。

相关问题