我想要使用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} param从未被实际值取代。这让我想到了我的问题的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”替换。 param提供:
[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/'},
)
但这感觉很骇人听闻,应该完全没必要。所以......
这里是视图集
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={})]
根据Injurk的建议,我将所有内容缩减为默认值 - 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
是其他字段,则永远不会插入网址lookup_field
占位符。
我不知道该怎么做。 CID是必须要求的......
答案 0 :(得分:1)
好吧,我发现了这个问题。 :-) cid
必须设置为readonly,然后正确形成PUT / PATCH的URL。
为什么lookup_field
必须只读?如果lookup_field
可写不正确且不可行,则错误消息将非常有用,而不是当前行为。
嗯谢谢,@ hurkurk!我没注意到你的PR!这确实解决了我的问题,至少在cid
不需要编辑时。将路径参数与请求数据分开指定真的很棒,这样可以在PUT / PATCH上更改lookup_field
值。但这是另一场讨论。
答案 1 :(得分:0)
这肯定是CoreAPI http传输的一个错误,因为它假设架构中的所有字段名称都是不同的。我提供了PR来修复它,但项目所有者可能需要进一步的设计考虑。
正如您所提到的,将查找字段设置为只读是该问题的替代解决方案,因为这会导致它在字段分析中仅出现一次。