2016-12-26 61 views
2

有一個使用REST API的Django項目。Django REST:在1個url上顯示詳細信息和列表

大多數鏈接圖案的遵循相同的範例:

/foo_config/1 

基本上/list-view/details-view

但還有另一種類型的配置的 - 這隻能有1個對象,所以示出了它喜歡/bar_config/1是混亂的,因爲用戶可能會期望#2和#3等。

我想'映射'bar_config細節和列表一起使用簡單/bar_config

使用@detail_route試過,但它不工作:

@detail_route(methods=['put']) 
def put_config(self, request): 
    ... 

如何實現我的目標?

更新:在嘗試玩detail_route和伊萬Semochkin答案 - 仍然沒有運氣。我將提供什麼,我有更多的細節:

/accounts/foo_account/bar_config/ < - 列表視圖 /accounts/foo_account/bar_config/1 < - 詳細信息視圖定義爲

帳戶:

router = routers.DefaultRouter() 
router.register('accounts', AccountViewSet) 

目標是:

  1. 顯示bar_config/1bar_config(PUT在LIST頁面上);
  2. 禁止/隱藏bar_config/1;
  3. 允許查看和更新​​信息,禁止創建/刪除;

我會總結一下:我需要改變子鏈接在現有項目中的工作方式,它已經在所有模式中使用DefaultRouter。這個子鏈接映射單例模型。我想在列表(GET)頁面上顯示更新(PUT)數據。

回答

5

爲什麼不重寫list方法?

class ConfigViewSet(viewsets.ReadOnlyModelViewSet): 

    queryset = Config.objects.all() 
    serializer_class = ConfigSerializer 

    def retrieve(self, request, *args, **kwargs): 
     return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) 

    def list(self, request, *args, **kwargs): 
     instance = self.get_queryset().first() 
     # using 'first' will retrieve first instance 
     serializer = self.get_serializer(instance) 
     return Responce(serializer.data) 

它會正常工作,你不僅顯示該模型。如果您想提供一些CRUD,則繼承ModelViewSet並覆蓋deleteupdate方法。
更新評論
另一種方式來做到這一點 - 創建一個自定義的路由器,這個路由器使用list,使用檢索到您並不需​​要,而不是

from rest_framework.routers import Route, SimpleRouter 

class CustomRouter(SimpleRouter): 
""" 
A router for update and retrieve without lookup field. 
""" 
    routes = [ 
     Route(
      url=r'^{prefix}/$', 
      mapping={'put': 'update'}, 
      name='{basename}-update', 
      initkwargs={'suffix': 'Update'} 
     ), 
     Route(
      url=r'^{prefix}/$', 
      mapping={'get': 'retrieve'}, 
      name='{basename}-detail', 
      initkwargs={'suffix': 'Detail'} 
     ), 
    ] 

視圖集:

class ConfigViewSet(viewsets.ModelViewSet): 

    queryset = Config.objects.all() 
    serializer_class = ConfigSerializer 

    def retrieve(self, request, *args, **kwargs): 
     instance = self.get_queryset().first() 
     # using 'first' will retrieve first instance 
     serializer = self.get_serializer(instance) 
     return Responce(serializer.data) 

    def update(self, request, *args, **kwargs): 
     instance = self.get_queryset().first() 
     serializer = self.get_serializer(instance, data=request.data) 
     # you could also provide `partial=True` in serializer for partial update 
     if serializer.is_valid(): 
      serializer.save() 
      return Responce(serializer.data) 
     else: 
      return Responce(serializer.errors) 

網址:

router = CustomRouter() 
router.register('config', ConfigViewSet) 
urlpatterns = router.urls 
+0

我需要一個只讀模型(no創建,不刪除)。也希望能夠直接在列表視圖上放置。 – Oleg

+0

@ h3d0所以你可以使用'ModelViewSet'來代替,並執行與'retrieve'方法相同的操作。但是'put'有一個問題,你需要覆蓋默認的url,因爲默認情況下它是w8的查找字段,就像pk在檢索中一樣。 –

+0

這是一個問題:如何覆蓋'put'中的默認網址。 – Oleg