Disable a method in a ViewSet, django-rest-framework
The definition of ModelViewSet
is:
class ModelViewSet(mixins.CreateModelMixin,
mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet)
So rather than extending ModelViewSet
, why not just use whatever you need? So for example:
from rest_framework import viewsets, mixins
class SampleViewSet(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
...
With this approach, the router should only generate routes for the included methods.
Reference:
ModelViewSet
You could keep using viewsets.ModelViewSet
and define http_method_names
on your ViewSet.
Example
class SampleViewSet(viewsets.ModelViewSet):
queryset = api_models.Sample.objects.all()
serializer_class = api_serializers.SampleSerializer
http_method_names = ['get', 'post', 'head']
Once you add http_method_names
, you will not be able to do put
and patch
anymore.
If you want put
but don't want patch
, you can keep http_method_names = ['get', 'post', 'head', 'put']
Internally, DRF Views extend from Django CBV. Django CBV has an attribute called http_method_names. So you can use http_method_names with DRF views too.
[Shameless Plug]: If this answer was helpful, you will like my series of posts on DRF at https://www.agiliq.com/blog/2019/04/drf-polls/.
Although it's been a while for this post, I suddenly found out that actually there is a way to disable those functions, you can edit it in the views.py directly.
Source: https://www.django-rest-framework.org/api-guide/viewsets/#viewset-actions
from rest_framework import viewsets, status
from rest_framework.response import Response
class NameThisClassWhateverYouWantViewSet(viewsets.ModelViewSet):
def create(self, request):
response = {'message': 'Create function is not offered in this path.'}
return Response(response, status=status.HTTP_403_FORBIDDEN)
def update(self, request, pk=None):
response = {'message': 'Update function is not offered in this path.'}
return Response(response, status=status.HTTP_403_FORBIDDEN)
def partial_update(self, request, pk=None):
response = {'message': 'Update function is not offered in this path.'}
return Response(response, status=status.HTTP_403_FORBIDDEN)
def destroy(self, request, pk=None):
response = {'message': 'Delete function is not offered in this path.'}
return Response(response, status=status.HTTP_403_FORBIDDEN)
If you are trying to disable the PUT method from a DRF viewset, you can create a custom router:
from rest_framework.routers import DefaultRouter
class NoPutRouter(DefaultRouter):
"""
Router class that disables the PUT method.
"""
def get_method_map(self, viewset, method_map):
bound_methods = super().get_method_map(viewset, method_map)
if 'put' in bound_methods.keys():
del bound_methods['put']
return bound_methods
By disabling the method at the router, your api schema documentation will be correct.