禁用ViewSet,django-rest-framework中的方法

db0*_*db0 102 python django django-views django-rest-framework

ViewSets 有自动方法来列出,检索,创建,更新,删除,...

我想禁用其中的一些,我想出的解决方案可能不是一个好的,因为OPTIONS仍然表示允许的那些.

关于如何以正确的方式做到这一点的任何想法?

class SampleViewSet(viewsets.ModelViewSet):
    queryset = api_models.Sample.objects.all()
    serializer_class = api_serializers.SampleSerializer

    def list(self, request):
        return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
    def create(self, request):
        return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED)
Run Code Online (Sandbox Code Playgroud)

Sun*_*eUp 214

定义ModelViewSet是:

class ModelViewSet(mixins.CreateModelMixin, 
                   mixins.RetrieveModelMixin, 
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet)
Run Code Online (Sandbox Code Playgroud)

因此ModelViewSet,为什么不只是使用你需要的东西而不是延伸?例如:

from rest_framework import viewsets, mixins

class SampleViewSet(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    viewsets.GenericViewSet):
    ...
Run Code Online (Sandbox Code Playgroud)

使用这种方法,路由器应该只为包含的方法生成路由.

参考:

ModelViewSet

  • @MuneebAhmad PATCH方法是从UpdateModelMixin启用的。如果您想使用更新而不是补丁,我目前可以想到两种方法。您可以覆盖视图中允许的方法并删除“补丁”,也可以覆盖`partial_update`方法并调用`http_method_not_allowed(request,* args,** kwargs)`。我还没有测试过,所以不确定它是否有效 (3认同)
  • 只需要使用mixin,就可以禁用GET,POST,PUT,DELETE方法,但是我无法找出如何禁用PATCH方法(特别是在使用路由器时)。 (2认同)
  • 如果有人想制作只读视图集,那么他们可以使用“class SampleViewSet(viewsets.ReadOnlyModelViewSet)”。 (2认同)

Aks*_*aaj 108

您可以继续在ViewSet上使用viewsets.ModelViewSet和定义http_method_names.

class SampleViewSet(viewsets.ModelViewSet):
    queryset = api_models.Sample.objects.all()
    serializer_class = api_serializers.SampleSerializer
    http_method_names = ['get', 'post', 'head']
Run Code Online (Sandbox Code Playgroud)

一旦你加入http_method_names,你将无法做到putpatch了.

如果你想put但又不想要patch,你可以保留http_method_names = ['get', 'post', 'head', 'put']

在内部,DRF Views从Django CBV扩展.Django CBV有一个名为http_method_names的属性.因此,您也可以将http_method_names与DRF视图一起使用.

  • 这种方式的问题是无法禁用列表或检索.必须禁用两者或两者都禁用 (10认同)
  • 这对我不起作用,在包含 get 和 head 之后,我仍然可以发帖 (2认同)
  • 我更喜欢这种方法,因为我无法将mixin的继承更改为包括PATCH,但不能将其更改为PUT,因为它们都是mixins.UpdateModelMixin的实现。 (2认同)

W K*_*nny 16

虽然这个帖子已经有一段时间了,但我突然发现实际上有一种方法可以禁用这些功能,您可以直接在views.py中编辑它。

来源: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)
Run Code Online (Sandbox Code Playgroud)

  • “HTTP_405_METHOD_NOT_ALLOWED”怎么样? (5认同)
  • 这应该是一个更好的方式。 (2认同)
  • 我还建议使用`raise MethodNotAllowed(request.method)` (2认同)

小智 8

如果您尝试从 DRF 视图集中禁用 PUT 方法,您可以创建自定义路由器:

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
Run Code Online (Sandbox Code Playgroud)

通过在路由器上禁用该方法,您的 api 架构文档将是正确的。


小智 6

我喜欢@pymen 答案的想法,但他的实现不起作用。这会:

class SampleViewSet(viewsets.ModelViewSet):
    http_method_names = [m for m in viewsets.ModelViewSet.http_method_names if m not in ['delete']]
Run Code Online (Sandbox Code Playgroud)

这样做的优点是实际上只进行排除并且很简单。虽然它看起来有点老套,但如果它仅适用于那个 ViewSet,则可能正是您所需要的。