I have not tested it myself, but I think you can do it by overriding the methods you need.
According to the documentation (note additional steps for routing):
class UserViewSet(viewsets.ViewSet): """ Example empty viewset demonstrating the standard actions that will be handled by a router class. If you're using format suffixes, make sure to also include the `format=None` keyword argument for each action. """ def list(self, request): pass def create(self, request): pass def retrieve(self, request, pk=None): pass def update(self, request, pk=None): pass def partial_update(self, request, pk=None): pass def destroy(self, request, pk=None): pass
Or if you need special methods:
from django.contrib.auth.models import User from rest_framework import status from rest_framework import viewsets from rest_framework.decorators import detail_route, list_route from rest_framework.response import Response from myapp.serializers import UserSerializer, PasswordSerializer class UserViewSet(viewsets.ModelViewSet): """ A viewset that provides the standard actions """ queryset = User.objects.all() serializer_class = UserSerializer @detail_route(methods=['post']) def set_password(self, request, pk=None): user = self.get_object() serializer = PasswordSerializer(data=request.DATA) if serializer.is_valid(): user.set_password(serializer.data['password']) user.save() return Response({'status': 'password set'}) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) @list_route() def recent_users(self, request): recent_users = User.objects.all().order('-last_login') page = self.paginate_queryset(recent_users) serializer = self.get_pagination_serializer(page) return Response(serializer.data)
source share