Add custom route to viewsets.ModelViewSet

The ViewSets docs mention using action decorator:

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)

Then just update your queryset to do whatever it needs to do.

The advantage of doing it this way is that your serialisation is preserved.

If your urls.py looks like this:

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)),
]

Then it is reachable via http://localhost:8000/snippets/highlights

To see usage for a POST, or how to change routing, see docs for routers.


Yes, you can do that. Just add your method in the viewset with the list_route decorator.

from rest_framework.decorators import list_route  

class SnippetViewSet(viewsets.ModelViewSet):
    ...

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

It will add a url without the pk param like :

r'^snippets/highlight/$'

You can even specify the methods it supports using the methods argument in your decorator.

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