1

我有这个模型:

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);
                            }
                        }
                    })

我从 PUT 请求中得到“ 202 ACCEPTED ”,并且朋友没有更新。

并且来自 PATCH 请求的“ 202 ACCEPTED ”,并且朋友没有更新。

如果我在创建 usersub 时在第一个发布请求中添加朋友,它会成功地将它们添加到数据库中。但是如果我使用 PUT 或 PATCH 向数组添加更多内容,则不会更新。

4

1 回答 1

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 资源,而父资源也存在于顶层的 ToMany 关系中。由于嵌套和资源上字段的顺序,操作的顺序是这样的:

  1. 将 usersubs 水合到包中(及其嵌套关系 - 从数据库加载,在我们的例子中为空)
  2. 将 specialUsersub 水合到包中(及其嵌套关系 - 包含在请求数据中)
  3. 保存 specialUsersub(嵌套资源正确保存在这里)
  4. [此时,tastepie 应该检查它的任何水合资源是否被保存并重新水合捆绑包的适当部分,但它没有,所以:]
  5. 保存 usersubs(如果 specialUsersub 的资源也存在于 usersubs 中,那么之前保存的内容将被第 1 步中 usersubs 水合时加载的过时数据覆盖)

更准确地说,因为 sweetpie 在用存储在包中的内容重新填充它们之前故意清除所有 m2m 关系,所以陈旧的数据破坏了新数据,在 3 中创建的朋友被删除并替换为在 1 中加载的 [] 空列表.

我仍在测试,但我认为解决方案/破解是确保您在任何您的美味派资源可能期望的地方包含更新的嵌套资源

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/"] } }

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

于 2013-04-30T18:20:59.573 回答