【问题标题】:Django Tastypie Many to Many (self) field update using a PATCH or PUT request?使用 PATCH 或 PUT 请求更新 Django Tastypie 多对多(自我)字段?
【发布时间】:2013-04-05 21:57:36
【问题描述】:

我有这个模型:

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 向数组添加更多内容,则不会更新。

【问题讨论】:

  • 这个实际代码有问题吗?或者这只是一个人为的例子?我认为您的示例中有几件事实际上可以使它在这种情况下起作用:1)您正在直接修补 UserSubResource 而不是 UserResource。 2)我认为问题与资源中多次出现的嵌套 M2M 有关,但您的示例只有单个相关的 ToManyField。我正在处理同样的问题并寻找解决方案。

标签: python django api rest tastypie


【解决方案1】:

我不能确定和你的情况一样,但我发现了我的问题。

让我稍微修改一下你的例子以反映我遇到的情况:

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 合并到包中(及其嵌套关系 - 从 DB 加载,在我们的示例中为空)
  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/"] } }

显然这并不理想。如果我想出更合适的解决方案,我会通知您。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-05
    • 1970-01-01
    • 2019-04-22
    • 1970-01-01
    • 2014-09-30
    • 2012-02-11
    • 1970-01-01
    相关资源
    最近更新 更多