Django-tastypie 不喜欢带有嵌套资源的 POST (full=True)

发布于 2025-01-05 02:31:57 字数 5749 浏览 0 评论 0 原文

我使用backbone-tastypie 来创建嵌套资源。

class ServiceResource(ModelResource):
    manager = fields.ToOneField(UserResource, 'manager',full=True)
    area = fields.ToOneField(AreaResource, 'area',full=True)
    specification = fields.ToManyField('services.api.ServiceSpecResource','servicespec_set',full=True)
    class Meta:
        queryset = Service.objects.all()
        resource_name = 'service'

class ServiceSpecResource(ModelResource):
    service = fields.ToOneField(ServiceResource,'service')
    servicespecrange = fields.ToManyField('services.api.ServiceSpecRangeResource','servicespecrange_set',full=True)
    servicespecconstant = fields.ToManyField('services.api.ServiceSpecConstantResource','servicespecconstant_set',full=True)
    servicespecgeneric = fields.ToManyField('services.api.ServiceSpecGenericResource','servicespecgeneric_set',full=True)
    class Meta:
        queryset = ServiceSpec.objects.all()
        resource_name = 'servicespec'
        list_allowed_methods = ['get', 'post']
        detail_allowed_methods = ['get', 'put', 'delete']
        authorization = DjangoAuthorization()

class ServiceSpecRangeResource(ModelResource):  
    servicespec = fields.ToOneField(ServiceSpecResource,'service_spec')
    class Meta:
        queryset = ServiceSpecRange.objects.all()
        resource_name = 'servicespecrange'

class ServiceSpecConstantResource(ModelResource):   
    servicespec = fields.ToOneField(ServiceSpecResource,'service_spec')
    class Meta:
        queryset = ServiceSpecConstant.objects.all()
        resource_name = 'servicespecconstant'

class ServiceSpecGenericResource(ModelResource):
    servicespec = fields.ToOneField(ServiceSpecResource,'service_spec')
    class Meta:
        queryset = ServiceSpecGeneric.objects.all()
        resource_name = 'servicespecgeneric'

对于获取 ServiceResource 来说它效果很好。我返回一个 Service 对象,其中包含所有 ServiceSpecification,而 ServiceSpecification 又包含所有 ServiceSpecRange/常量等。

将整个嵌套资源放回服务器也适用于现有数据。

但是,每当我尝试一次性发布整个嵌套资源(附加了新服务规范的新服务)时,我得到:

int() 参数必须是字符串或数字,而不是“列表”

我以前遇到过此错误,并发现它与不包含相关资源的resource_uri有关。但在这种情况下,我正在发布 - 所以它不应该抱怨嵌套资源中缺少resource_uri。未包含它们的原因是父资源尚未保存。 tastypie 还不够先进,看不到这个吗?

这是回溯:

{ "error_message":"int() 参数必须是字符串或数字,而不是 'list'", "traceback":"回溯(最近一次调用):

文件“build/bdist.linux-x86_64/egg/tastypie/resources.py”,第 192 行, 在包装器响应 = 回调(请求,*args,**kwargs)

F> ile \“build/bdist.linux-x86_64/egg/tastypie/resources.py\”,第 397 行, 在dispatch_list中返回self.dispatch('list', request, **kwargs)

文件“build/bdist.linux-x86_64/egg/tastypie/resources.py”,第 427 行, 在调度响应=方法(请求,**kwargs)

文件“build/bdist.linux-x86_64/egg/tastypie/resources.py”,行 第1165章 request=request, **self.remove_api_resource_names(kwargs))

文件“build/bdist.linux-x86_64/egg/tastypie/resources.py”,行 第1783章

文件“build/bdist.linux-x86_64/egg/tastypie/resources.py”,第743行, 在 Hydro_m2m 中。data[field_name] = field_object.水合物_m2m(捆绑)

文件“build/bdist.linux-x86_64/egg/tastypie/fields.py”,第 742 行,位于 水合物_m2m m2m_Hydrated.append(self.build_lated_resource(值, **夸格斯))

文件“build/bdist.linux-x86_64/egg/tastypie/fields.py”,第 593 行,位于 构建相关资源返回 self.resource_from_data(self.fk_resource, 值, **kwargs)

文件“build/bdist.linux-x86_64/egg/tastypie/fields.py”,第 548 行,位于 resource_from_data 返回 fk_resource.obj_update(fk_bundle, **data)

文件“build/bdist.linux-x86_64/egg/tastypie/resources.py”,行 第1814章 **lookup_kwargs)

文件“build/bdist.linux-x86_64/egg/tastypie/resources.py”,行 第1752章 self.get_object_list(request).filter(**kwargs)

文件 \“/usr/local/lib/python2.7/site-packages/django/db/models/query.py\”, 第 550 行,在过滤器中返回 self._filter_or_exclude(False, *args, **夸格斯)

文件 \“/usr/local/lib/python2.7/site-packages/django/db/models/query.py\”, 第 568 行,在 _filter_or_exclude 中clone.query.add_q(Q(*args, **kwargs))

文件 \“/usr/local/lib/python2.7/site-packages/django/db/models/sql/query.py\”, 第 1194 行,在 add_q can_reuse=used_aliases、force_having=force_having)

文件 \“/usr/local/lib/python2.7/site-packages/django/db/models/sql/query.py\”, 第 1129 行,在 add_filter 连接器中)

文件 \“/usr/local/lib/python2.7/site-packages/django/db/models/sql/where.py\”, 第 67 行,添加 value = obj.prepare(lookup_type, value)

文件 \“/usr/local/lib/python2.7/site-packages/django/db/models/sql/where.py\”, 第316行,在准备中返回self.field.get_prep_lookup(lookup_type, 值)

文件 \“/usr/local/lib/python2.7/site-packages/django/db/models/fields/lated.py\”, 第 136 行,在 get_prep_lookup 中返回 self._pk_trace(value, 'get_prep_lookup',lookup_type)

文件 \“/usr/local/lib/python2.7/site-packages/django/db/models/fields/lated.py\”, 第 209 行,在 _pk_trace v = getattr(field, prep_func)(lookup_type, v, **夸格斯)

文件 \“/usr/local/lib/python2.7/site-packages/django/db/models/fields/init.py\”, 第292行,在get_prep_lookup中返回self.get_prep_value(value)

文件 \“/usr/local/lib/python2.7/site-packages/django/db/models/fields/init.py\”, 第 479 行,在 get_prep_value 中返回 int(value)

类型错误:int() 参数必须是字符串或数字,而不是“列表”” }

编辑

我相信这个问题是相关的:

https://github.com/toastdriven/django-tastypie/issues/307

连同此测试用例:

https://github.com/joshbohde/django-tastypie/commit/eef8d27fb65d5777a98a3df034af26ceb317deb3

Im using backbone-tastypie to create a nested resource as so.

class ServiceResource(ModelResource):
    manager = fields.ToOneField(UserResource, 'manager',full=True)
    area = fields.ToOneField(AreaResource, 'area',full=True)
    specification = fields.ToManyField('services.api.ServiceSpecResource','servicespec_set',full=True)
    class Meta:
        queryset = Service.objects.all()
        resource_name = 'service'

class ServiceSpecResource(ModelResource):
    service = fields.ToOneField(ServiceResource,'service')
    servicespecrange = fields.ToManyField('services.api.ServiceSpecRangeResource','servicespecrange_set',full=True)
    servicespecconstant = fields.ToManyField('services.api.ServiceSpecConstantResource','servicespecconstant_set',full=True)
    servicespecgeneric = fields.ToManyField('services.api.ServiceSpecGenericResource','servicespecgeneric_set',full=True)
    class Meta:
        queryset = ServiceSpec.objects.all()
        resource_name = 'servicespec'
        list_allowed_methods = ['get', 'post']
        detail_allowed_methods = ['get', 'put', 'delete']
        authorization = DjangoAuthorization()

class ServiceSpecRangeResource(ModelResource):  
    servicespec = fields.ToOneField(ServiceSpecResource,'service_spec')
    class Meta:
        queryset = ServiceSpecRange.objects.all()
        resource_name = 'servicespecrange'

class ServiceSpecConstantResource(ModelResource):   
    servicespec = fields.ToOneField(ServiceSpecResource,'service_spec')
    class Meta:
        queryset = ServiceSpecConstant.objects.all()
        resource_name = 'servicespecconstant'

class ServiceSpecGenericResource(ModelResource):
    servicespec = fields.ToOneField(ServiceSpecResource,'service_spec')
    class Meta:
        queryset = ServiceSpecGeneric.objects.all()
        resource_name = 'servicespecgeneric'

For getting the ServiceResource it works great. I get back a Service object back which contains all the ServiceSpecification's which in turn has all the ServiceSpecRange's/constants etc.

Putting the whole nested resource back to the server also works fine for existing data.

However, whenever I try to post a whole nested resource in one go (new service with new servicespec attached) I get:

int() argument must be a string or a number, not 'list'

I have had this error before, and found it related to not including a resource_uri to a related resource. But in this case, i'm posting - so it shouldn't be complaining about missing resource_uri's in a nested resource. The reason they aren't included is because the parent resource hasn't been saved yet. Is tastypie not advanced enough to see this?

Here is the traceback:

{ "error_message":"int() argument must be a string or a number, not
'list'", "traceback":"Traceback (most recent call last):

File \"build/bdist.linux-x86_64/egg/tastypie/resources.py\", line 192,
in wrapper response = callback(request, *args, **kwargs)

F> ile \"build/bdist.linux-x86_64/egg/tastypie/resources.py\", line 397,
in dispatch_list return self.dispatch('list', request, **kwargs)

File \"build/bdist.linux-x86_64/egg/tastypie/resources.py\", line 427,
in dispatch response = method(request, **kwargs)

File \"build/bdist.linux-x86_64/egg/tastypie/resources.py\", line
1165, in post_list updated_bundle = self.obj_create(bundle,
request=request, **self.remove_api_resource_names(kwargs))

File \"build/bdist.linux-x86_64/egg/tastypie/resources.py\", line
1783, in obj_create m2m_bundle = self.hydrate_m2m(bundle)

File \"build/bdist.linux-x86_64/egg/tastypie/resources.py\", line 743,
in hydrate_m2m bundle.data[field_name] =
field_object.hydrate_m2m(bundle)

File \"build/bdist.linux-x86_64/egg/tastypie/fields.py\", line 742, in
hydrate_m2m m2m_hydrated.append(self.build_related_resource(value,
**kwargs))

File \"build/bdist.linux-x86_64/egg/tastypie/fields.py\", line 593, in
build_related_resource return
self.resource_from_data(self.fk_resource, value, **kwargs)

File \"build/bdist.linux-x86_64/egg/tastypie/fields.py\", line 548, in
resource_from_data return fk_resource.obj_update(fk_bundle, **data)

File \"build/bdist.linux-x86_64/egg/tastypie/resources.py\", line
1814, in obj_update bundle.obj = self.obj_get(request,
**lookup_kwargs)

File \"build/bdist.linux-x86_64/egg/tastypie/resources.py\", line
1752, in obj_get base_object_list =
self.get_object_list(request).filter(**kwargs)

File
\"/usr/local/lib/python2.7/site-packages/django/db/models/query.py\",
line 550, in filter return self._filter_or_exclude(False, *args,
**kwargs)

File
\"/usr/local/lib/python2.7/site-packages/django/db/models/query.py\",
line 568, in _filter_or_exclude clone.query.add_q(Q(*args, **kwargs))

File
\"/usr/local/lib/python2.7/site-packages/django/db/models/sql/query.py\",
line 1194, in add_q can_reuse=used_aliases, force_having=force_having)

File
\"/usr/local/lib/python2.7/site-packages/django/db/models/sql/query.py\",
line 1129, in add_filter connector)

File
\"/usr/local/lib/python2.7/site-packages/django/db/models/sql/where.py\",
line 67, in add value = obj.prepare(lookup_type, value)

File
\"/usr/local/lib/python2.7/site-packages/django/db/models/sql/where.py\",
line 316, in prepare return self.field.get_prep_lookup(lookup_type,
value)

File
\"/usr/local/lib/python2.7/site-packages/django/db/models/fields/related.py\",
line 136, in get_prep_lookup return self._pk_trace(value,
'get_prep_lookup', lookup_type)

File
\"/usr/local/lib/python2.7/site-packages/django/db/models/fields/related.py\",
line 209, in _pk_trace v = getattr(field, prep_func)(lookup_type, v,
**kwargs)

File
\"/usr/local/lib/python2.7/site-packages/django/db/models/fields/init.py\",
line 292, in get_prep_lookup return self.get_prep_value(value)

File
\"/usr/local/lib/python2.7/site-packages/django/db/models/fields/init.py\",
line 479, in get_prep_value return int(value)

TypeError: int() argument must be a string or a number, not 'list' " }

EDIT:

I believe this issue is related:

https://github.com/toastdriven/django-tastypie/issues/307

Along with this test case:

https://github.com/joshbohde/django-tastypie/commit/eef8d27fb65d5777a98a3df034af26ceb317deb3

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

我不是你的备胎 2025-01-12 02:31:57

这已在另一个分支中修复。请参阅拉取请求

This has been fixed in another branch. See the pull request.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文