Не поддерживает ли rest_framework coreapi PUT / PATCH?
Я хочу использовать клиентскую библиотеку Python, но у меня нет конца с трудом заставить работать PUT/PATCH. Всякий раз, когда я пытаюсь использовать update / частичный_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
}
Теперь, когда я провёл большую часть утра, пытаясь заставить это работать, я понял, что нет примера документации, показывающего обновление / частичное обновление.
Так что я решил попробовать 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
это не ПК), а 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, тогда URL PUT/PATCH генерируется правильно. когда lookup_field
какое-то другое поле, то URL lookup_field
заполнитель никогда не интерполируется.
Я не знаю что делать. CID является обязательным требованием...
2 ответа
Ну, я нашел проблему.:-) cid
должен быть установлен только для чтения, и тогда URL для PUT/PATCH сформирован правильно.
Почему должен lookup_field
быть только для чтения? Если это неправильно и неработоспособно иметь lookup_field
быть доступным для записи, сообщение об ошибке было бы очень полезно, вместо текущего поведения.
редактировать
Ну, спасибо, @hurkurk! Я не заметил твой пиар! Это решает мою проблему, по крайней мере, когда cid
не нужно редактировать. Было бы здорово, если бы параметр пути был указан отдельно от данных запроса, чтобы lookup_field
значение может быть изменено на PUT/PATCH. Но это другое обсуждение.
Это, безусловно, ошибка в HTTP-транспорте CoreAPI, поскольку предполагается, что все имена полей в схеме различны. Я предоставил PR, чтобы исправить это, но это может потребовать дополнительных конструктивных соображений со стороны владельца проекта.
Как вы также упомянули, создание поля поиска только для чтения является альтернативным решением проблемы, поскольку это может привести к тому, что оно появится только один раз в полевом анализе.