2016-12-26 72 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