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

时间:2014-05-13 18:40:36

标签: 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)

9 个答案:

答案 0 :(得分:190)

ModelViewSet的定义是:

class ModelViewSet(mixins.CreateModelMixin, 
                   mixins.RetrieveModelMixin, 
                   mixins.UpdateModelMixin,
                   mixins.DestroyModelMixin,
                   mixins.ListModelMixin,
                   GenericViewSet)

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

from rest_framework import viewsets, mixins

class SampleViewSet(mixins.RetrieveModelMixin,
                    mixins.UpdateModelMixin,
                    mixins.DestroyModelMixin,
                    viewsets.GenericViewSet):
    ...

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

<强>参考

ModelViewSet

答案 1 :(得分:88)

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

实施例

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

添加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视图一起使用。

[无耻的插件]:如果这个答案有帮助,你会在https://www.agiliq.com/blog/2019/04/drf-polls/上看到我在DRF上的一系列帖子。

答案 2 :(得分:9)

尽管这篇文章已经有一段时间了,但我突然发现实际上有一种禁用这些功能的方法,您可以直接在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)

答案 3 :(得分:3)

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

 "NA/701F0000006Iw8E/701F0000006Iw8Y/701F0000006IS1t" for "Bing ABC"

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

答案 4 :(得分:3)

我喜欢@pymen 回答的想法,但他的实现没有奏效。这样做:

class SampleViewSet(viewsets.ModelViewSet):
    http_method_names = [m for m in viewsets.ModelViewSet.http_method_names if m not in ['delete']]

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

答案 5 :(得分:1)

如何在DRF中禁用ViewSet的“删除”方法

class YourViewSet(viewsets.ModelViewSet):
    http_method_names = [m for m in super().http_method_names if m != 'delete']

P.S。这比显式指定所有必要方法更可靠,因此,忘记一些重要方法OPTIONS,HEAD等的机会较小

P.P.S。 默认情况下,DRF具有http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']

答案 6 :(得分:1)

在Django Rest Framework 3.x.x中,您可以通过将字典传递给ModelViewSet方法来简单地启用要为as_view启用的每个方法。在此字典中,键必须包含请求类型(GET,POST,DELETE等),并且值必须包含相应的方法名称(列表,检索,更新等)。例如,假设您要创建或读取Sample模型,但不希望对其进行修改。因此,这意味着您希望启用listretrievecreate方法(并且希望禁用其他方法。)

您需要做的就是像下面这样向urlpatterns添加路径:

path('sample/', SampleViewSet.as_view({
    'get': 'list',
    'post': 'create'
})),
path('sample/<pk>/', SampleViewSet.as_view({  # for get sample by id.
    'get': 'retrieve'
}))

如您所见,上述路由设置中没有deleteput请求,因此,例如,如果您向网址发送put请求,它将以405 {{ 1}}:

Method Not Allowed

答案 7 :(得分:0)

如果您打算禁用放置/发布/销毁方法,则可以使用

viewsets.ReadOnlyModelViewSet https://www.django-rest-framework.org/tutorial/6-viewsets-and-routers/#refactoring-to-use-viewsets

答案 8 :(得分:0)

禁用视图集上的方法,使您的api上的内容保持一致并返回有用的错误消息的最直接方法是简单地针对您不想使用的任何方法引发MethodNotAllowed异常。对于像GET这样映射为在禁用列表的情况下进行检索和列出的方法,您可以自定义错误消息,以指示GET仅适用于URL上的查找值。

from rest_framework.exceptions import MethodNotAllowed

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

def list(self, request):
    raise MethodNotAllowed('GET', detail='Method "GET" not allowed without lookup')
def create(self, request):
    raise MethodNotAllowed(method='POST')

这将以DRF使用的格式返回405状态码和json数据:

{'detail': 'Method "POST" not allowed.'}