2017-06-06 47 views
1

我想使用Python Client Library,但無法讓PUT/PATCH正常工作。每當我嘗試使用更新/ partial_update的URL參數是不是從字典插值,並且服務器返回404rest_framework coreapi不支持PUT/PATCH嗎?

[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的的logline顯示,URL PARAM從來沒有從 'CID' PARAM提供取代:

[06-Jun-2017 13:07:01] WARNING [django.server:124] "PUT /api/accounts/networks/%7Bcid%7D/ HTTP/1.1" 404 23 

我可以使用覆蓋PARAMS迫使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/'}, 
     ) 

但是,這感覺haaacky,應該是完全沒有必要的。所以...

  1. 這是一個錯誤?
  2. 我得到的函數簽名是否錯誤?
  3. 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.ModelViewsetserializers.ModelSerializer,並把lookup_fieldNetworksViewSet。仍是同樣的問題。

然後,我刪除了自定義查找字段,並試圖使用默認的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永遠不會插入。

我不知道該怎麼做。 CID是必備的要求...

+0

您的觀點如何? CoreAPI首先獲取由DRF提供的模式。 – hurturk

+0

看起來像CoreAPI的錯誤,因爲它已經是param safe了。還有兩個問題,你在哪裏定義你的'lookup_field'?以防萬一,你能否註釋掉過濾器並重試?你也可以從'cid'中刪除引號,這也可以。 – hurturk

+0

我簡化了此故障單中的視圖集,並忘記了編輯從故障診斷代碼中刪除了lookup_field聲明。現在編輯該問題,並顯示視圖集類層次結構。我沒有關注「從cid中刪除引號」,應該在哪裏完成? – Thinkwell

回答

1

嗯,我發現了這個問題。 :-) cid必須設置爲只讀,然後正確形成PUT/PATCH的URL。

爲什麼lookup_field只能讀取?如果這是不正確的,並且不可行,那麼可以寫入一個錯誤消息,而不是當前的行爲。

編輯

謝謝,@hurkurk!我沒有注意到你的PR!這確實解決了我的問題,至少在cid不需要編輯時。如果將路徑參數與請求數據分開指定,那麼真的會非常好,因此可以在PUT/PATCH上更改值lookup_field。但那是另一個討論。

+0

聽起來不錯!因爲這也是在安寧的討論設計PUT/PATCH是否應該在DRF中允許的情況下重命名資源,而不會出現問題。 – hurturk

0

這肯定是CoreAPI http傳輸的一個錯誤,因爲它假定模式中的所有字段名都是不同的。我提供了一個PR來修復它,但這可能需要項目所有者進一步的設計考慮。

正如您所提到的,使查找字段爲只讀是該問題的替代解決方案,因爲這會使其在字段分析中僅出現一次。