【发布时间】:2017-11-07 19:59:18
【问题描述】:
我想使用Python Client Library,但是让 PUT/PATCH 工作的痛苦无穷无尽。每当我尝试使用 update / partial_update 时,都不会从字典中插入 URL 参数,并且服务器会返回 404。
[06-Jun-2017 12:30:05] WARNING [django.server:124] "PUT /api/accounts/networks/%7Bcid%7D/ HTTP/1.1" 404 23
这清楚地表明 {cid} 参数从未被实际值替换。这让我想到了我的问题的 TL/DR 版本,CoreAPI 不支持 PUT / PATCH 吗?
PUT / PATCH 选项已根据以下信息正确设置:
GET /api/accounts/networks/2892c424-3a86-16bb-8b60-12a79900e90c/
HTTP 200 OK
Allow: GET, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept
{
"url": "http://localhost:8000/api/accounts/networks/2892c424-3a86-16bb-8b60-12a79900e8fb/",
"created": "2016-04-16T19:35:02.169898Z",
"modified": "2017-05-30T17:25:29.768740Z",
"cid": "2892c424-3a86-16bb-8b60-12a79900e8fb",
"name": "10.0.0.0/8",
"comments": "Local Area Network - 10.x",
"builtin": true
}
现在我花了一个上午的大部分时间来尝试完成这项工作,我意识到有 no documentation example 显示更新/部分更新。
所以我想我会尝试改用coreapi-cli,但我遇到了同样的问题。
coreapi action networks partial_update --param cid='2892c424-3a86-16bb-8b60-12a79900e8fb' --param comments='this is WAAAY too hard'
<Error: 404 Not Found>
detail: "Not found."
Django 的日志显示 URL 参数从未被提供的“cid”参数替换:
[06-Jun-2017 13:07:01] WARNING [django.server:124] "PUT /api/accounts/networks/%7Bcid%7D/ HTTP/1.1" 404 23
我可以使用覆盖参数来强制 URL,现在它会按预期更新。
client.action(['networks', 'partial_update'],
params={'comments': 'this is WAAAY too hard', 'cid': '2892c424-3a86-16bb-8b60-12a79900e8fb'},
overrides={'url': 'http://localhost:8000/api/accounts/networks/2892c424-3a86-16bb-8b60-12a79900e8fb/'},
)
但这感觉很糟糕,应该完全没有必要。所以...
- 这是一个错误吗?
- 我的函数签名有误吗?
- CoreAPI 不支持 PUT / PATCH 方法吗?
编辑
这是视图集
class LCModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
"""
Base ModelViewSet
"""
lookup_field = 'cid'
class NetworksViewSet(LCModelViewSet):
queryset = Networks.objects.all()
serializer_class = NetworksSerializer
filter_class = NetworksFilter
和路由器
router = DefaultRouter()
router.register(r'accounts/networks', av.NetworksViewSet, base_name='api-networks')
以及router.routes的输出
[Route(url='^{prefix}{trailing_slash}$', mapping={'get': 'list', 'post': 'create'}, name='{basename}-list', initkwargs={'suffix': 'List'}),
DynamicListRoute(url='^{prefix}/{methodname}{trailing_slash}$', name='{basename}-{methodnamehyphen}', initkwargs={}),
Route(url='^{prefix}/{lookup}{trailing_slash}$', mapping={'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'}, name='{basename}-detail', initkwargs={'suffix': 'Instance'}),
DynamicDetailRoute(url='^{prefix}/{lookup}/{methodname}{trailing_slash}$', name='{basename}-{methodnamehyphen}', initkwargs={})]
编辑#2
根据hurturk 的建议,我将所有内容都减少为默认值 - views.ModelViewset 和 serializers.ModelSerializer,并将 lookup_field 放在 NetworksViewSet 上。还是一样的问题。
然后我删除了自定义查找字段,并尝试使用默认的 id 字段(cid 不是 PK),然后 VOILA、PUT/PATCH 工作 - URL 生成正确!所以,我想知道是否出于某种原因它是一个与 UUID 相关的问题。
由于name 是一个唯一字段,我设置了lookup_field = name。与 UUID 相同的行为。 GET/POST 方法有效。 PUT/PATCH 不要"PATCH /api/accounts/networks/%7Bname%7D/ HTTP/1.1" 404 23。
看来,当lookup_field 是PK 时,PUT/PATCH url 会正确生成。当lookup_field 是其他字段时,永远不会插入 URL lookup_field 占位符。
我不知道该怎么办。 CID 是必备要求...
【问题讨论】:
-
您的视图看起来如何? CoreAPI 首先获取 DRF 提供的架构。
-
看起来像 CoreAPI 的一个错误,因为它已经是参数安全的。还有两个问题,你在哪里定义你的
lookup_field?以防万一,您可以注释掉过滤器并重试吗?您还可以从cid中删除引号,这也可以。 -
我简化了这张票中的视图集,忘记了编辑从票号中删除了 lookup_field 声明。现在编辑了问题,并显示了视图集类层次结构。我没有关注您关于“从
cid中删除引号。应该在哪里完成? -
哦,我的意思是
coreapi-cli,但应该没什么区别。我仍然认为这是一个错误,您的代码和调用对我来说看起来很完美。您可以删除继承的类,将NetworksViewSet中的lookup_field移动并让它从viewsets.ModelViewSet扩展,然后再报告此问题(以证明最小示例不起作用)。 -
我已经用
python 3.4.3、coreapi 2.3.1、coreapi-cli 1.0.6、django 1.11、djangorestframework 3.6.2测试了你的模型,效果很好。
标签: python django django-rest-framework core-api