Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/332.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django Tastypie使用补丁或PUT请求进行多对多(自我)字段更新?_Python_Django_Api_Rest_Tastypie - Fatal编程技术网

Python Django Tastypie使用补丁或PUT请求进行多对多(自我)字段更新?

Python Django Tastypie使用补丁或PUT请求进行多对多(自我)字段更新?,python,django,api,rest,tastypie,Python,Django,Api,Rest,Tastypie,我有这个模型: class UserSub(models.Model): user = models.OneToOneField(User, related_name='userSub') amigos = models.ManyToManyField('self', null=True) title = models.TextField() 导入的Django用户模型 以及下列资源: class UserResource(ModelResource): use

我有这个模型:

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'] 
我正在尝试更新特定用户的amigos值。我的数据是:

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已接受”,并且朋友没有更新

并且从补丁请求中“202已接受”,并且不更新AMIGO


如果我在创建usersub时在第一个post请求中添加了amigos,它会成功地将它们添加到数据库中。但如果我使用PUT或PATCH向阵列添加更多内容,则不会更新。

我不能确定这是否与您的情况相同,但我发现了我的问题

让我稍微修改一下您的示例,以反映我遇到的情况:

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关系中。由于嵌套和资源上字段的顺序,操作顺序如下:

  • 将usersubs添加到bundle中(及其嵌套关系-从DB加载,在本例中为空)
  • 将specialUsersub合并到包中(及其嵌套关系-包含在请求数据中)
  • 保存specialUsersub(嵌套资源正确保存在此处)
  • [此时,tastypie应检查其水合资源是否已保存,并对捆绑包的适当部分进行再水合,但事实并非如此,因此:]
  • 保存usersubs(如果specialUsersub上的资源也存在于usersubs中,则先前保存的内容将被在步骤1中水合usersubs时加载的陈旧数据覆盖)
  • 更准确地说,因为tastypie在使用包中存储的内容重新填充m2m关系之前故意清除所有m2m关系,陈旧数据会阻塞新数据,所以在3中创建的好友会被删除,并替换为在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/"] } }
    

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

    这段实际代码有问题吗?还是这只是一个人为的例子?在您的示例中,有两件事我认为在本例中确实可以起作用:1)您直接修补UserSubResource,而不是UserResource。2) 我认为这个问题与嵌套的M2M在资源中多次出现有关,但是您的示例只有一个与ToManyField相关的字段。我正在处理同样的问题,寻找解决办法。