Disable a method in a ViewSet, django-rest-framework

我们两清 提交于 2019-11-29 18:58:39

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/.

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.

How to disable "DELETE" method for ViewSet in DRF

class YourViewSet(viewsets.ModelViewSet):
    def _allowed_methods(self):
        return [m for m in super(YourViewSet, self)._allowed_methods() if m not in ['DELETE']]

P.S. This is more reliable than explicitly specifying all the necessary methods, so there is less chance of forgetting some of important methods OPTIONS, HEAD, etc

P.P.S. by default DRF has http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!