Django REST:在1个网址上显示详细信息和列表

0le*_*leg 2 python django django-rest-framework

有一个使用REST API的Django项目.

大多数url模式遵循相同的范例:

/foo_config/1
Run Code Online (Sandbox Code Playgroud)

基本上 /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):
  ...
Run Code Online (Sandbox Code Playgroud)

如何实现我的目标?

更新:尝试detail_route与Ivan Semochkin 一起玩后回答 - 仍然没有运气.我会提供更多有关我所拥有的细节:

/accounts/foo_account/bar_config/< - list view /accounts/foo_account/bar_config/1< - 详细信息视图

帐户定义为:

router = routers.DefaultRouter()
router.register('accounts', AccountViewSet)
Run Code Online (Sandbox Code Playgroud)

目标是:

  1. 显示bar_config/1bar_config(列表页上PUT);
  2. 禁止/隐藏bar_config/1;
  3. 允许查看和更新​​信息,禁止创建/删除;

我将总结一下:我需要改变现有项目中子链接的工作方式,该方法已经DefaultRouter用于其所有模式.该子链接映射单例模型.我想在列表(GET)页面上显示更新(PUT)数据.

Iva*_*kin 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)
Run Code Online (Sandbox Code Playgroud)

它会工作正常,你不仅要显示该模型.如果你想提供一些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'}
        ),
    ]  
Run Code Online (Sandbox Code Playgroud)

视图集:

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)
Run Code Online (Sandbox Code Playgroud)

网址:

router = CustomRouter()
router.register('config', ConfigViewSet)
urlpatterns = router.urls
Run Code Online (Sandbox Code Playgroud)