将自定义路由添加到viewsets.ModelViewSet

Dea*_*dly 7 django django-rest-framework

在文档中有自定义URL的方法示例:http: //www.django-rest-framework.org/tutorial/6-viewsets-and-routers

class SnippetViewSet(viewsets.ModelViewSet):
    ...

    @link(renderer_classes=[renderers.StaticHTMLRenderer])
    def highlight(self, request, *args, **kwargs):
        snippet = self.get_object()
        return Response(snippet.highlighted)
Run Code Online (Sandbox Code Playgroud)

此示例添加以下路由:

url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', snippet_highlight, name='snippet-highlight'),
Run Code Online (Sandbox Code Playgroud)

可以添加没有pk param的url,像这样吗?

r'^snippets/highlight/$'
Run Code Online (Sandbox Code Playgroud)

Rah*_*pta 10

是的,你可以这样做.只需使用list_route装饰器在视图集中添加您的方法即可.

from rest_framework.decorators import list_route  

class SnippetViewSet(viewsets.ModelViewSet):
    ...

    @list_route(renderer_classes=[renderers.StaticHTMLRenderer])
    def highlight(self, request, *args, **kwargs):
        ...
Run Code Online (Sandbox Code Playgroud)

它将添加一个没有pkparam 的url :

r'^snippets/highlight/$'
Run Code Online (Sandbox Code Playgroud)

您甚至可以使用methods装饰器中的参数指定它支持的方法.

http://www.django-rest-framework.org/api-guide/routers/#usage

  • 在最近的版本中@list_route()被替换为@action(detail=False),参见下面@Roman的回答 (3认同)

Rom*_*man 8

ViewSets文档提用action装饰:

from rest_framework.decorators import action


class SnippetViewSet(viewsets.ModelViewSet):
    ...

    @action(detail=False, methods=['GET'], name='Get Highlight')
    def highlight(self, request, *args, **kwargs):
        queryset = models.Highlight.objects.all()

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)
Run Code Online (Sandbox Code Playgroud)

然后只需更新您的queryset即可执行所需的任何操作。

这样做的好处是保留了序列化。

如果您urls.py看起来像这样:

from django.contrib import admin
from django.urls import path, include

from rest_framework import routers
from snippets import viewsets

router = routers.DefaultRouter()
router.register('snippets', viewsets.SnippetViewSet)

urlpatterns = [
    path('admin/', admin.site.urls),
    path('snippets/', include(router.urls)),
]
Run Code Online (Sandbox Code Playgroud)

然后可以通过 http://localhost:8000/snippets/highlights

要查看的用法POST或如何更改路由,请参阅docs路由器


bey*_*int 7

由于这个问题仍然出现在第一个 Google 页面上,这里是最新的(2020 年 3 月下旬)片段(双关语),用于开始处理单个对象的自定义 ModelViewSet 路由:

from rest_framework.decorators import action


class SnippetViewSet(viewsets.ModelViewSet):
    ...

    @action(detail=True, methods=['POST'], name='Attach meta items ids')
    def custom_action(self, request, pk=None):
        """Does something on single item."""
        queryset = Snippet.objects.get(pk=pk)
        serializer = self.get_serializer(queryset, many=False)
        return Response(serializer.data)
Run Code Online (Sandbox Code Playgroud)

拥有 DRF 教程中的默认路由器将允许您通过以下方式访问此路由: http://localhost:8000/snippets/<int:pk>/custom_action/

  • @CSZ只需设置`detail=False`。不知何故,Django 的人们选择将“detail”作为主键。˙\_(ツ)_/˙ (5认同)