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


123

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)

Answers:


250

的定义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):
    ...

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

参考

模型视图集


@SunnySydeUp现在尝试一下,看来路由器确实为列表视图生成了路由,但是它却是404s,因为ViewSet不知道如何处理请求。这是您所期望的吗?
史蒂夫·贾利姆

3
只需要使用mixin,就可以禁用GET,POST,PUT,DELETE方法,但是我无法找出如何禁用PATCH方法(特别是在使用路由器时)。
Muneeb Ahmad 2015年

3
@MuneebAhmad从中启用了PATCH方法UpdateModelMixin。如果您想使用更新而不是补丁,那么我目前可以想到两种方法。您可以覆盖视图中允许的方法并删除“补丁”,也可以覆盖partial_update方法并调用http_method_not_allowed(request, *args, **kwargs)。我尚未对此进行测试,所以不确定它是否有效
SunnySydeUp 2015年

1
@JulioMarins我添加了参考。我不确定这是否是您想要的。
SunnySydeUp

1
如果某人想制作只读视图集,则可以使用class SampleViewSet(viewsets.ReadOnlyModelViewSet)
比卡什哈雷尔

131

您可以继续使用viewsets.ModelViewSethttp_method_names在ViewSet上进行定义。

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视图从Django CBV扩展。Django CBV具有一个名为http_method_names的属性。因此,您也可以在DRF视图中使用http_method_names。

[Shameless Plug]:如果此答案有用,您将喜欢我在DRF上的系列文章,网址https://www.agiliq.com/blog/2019/04/drf-polls/


16
这种方法的问题是无法禁用列表或检索。必须禁用这两者或两者都不禁用
Fuad

1
这对我不起作用,包括get和head之后,我仍然可以发帖
RunLoop 2015年

这在django 1.9上对我有效。很好的解决方案。用户可以用其他方式执行GET请求是否存在风险?
Ycon

梦幻般的解决方案。工程于python3Django 1.10就好了。
Urda

2
我更喜欢这种方法,因为我无法将mixin的继承更改为包括PATCH,但不能将其更改为PUT,因为它们都是对 mixins.UpdateModelMixin
ThatsAMorais

5

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

这应该是一种更好的方法。
digitake

我认为,如果HTTP_400_BAD_REQUEST与auth不相关,则在此处更为合适。
圣地亚哥·马加里尼奥斯

4

如果尝试从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

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


由于在DRF中未正确实施部分补丁,因此明智的做法是按照此处所述的方法将其全局删除
奥登

1

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

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

PS这比显式指定所有必需的方法更可靠,因此很少有机会忘记一些重要的方法OPTIONS,HEAD等

默认情况下,DPS的PPS具有 http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']


您不能super在课堂上打电话,没有self
名称

0

在Django Rest Framework 3.xx中,您可以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'
}))

如您所见,上述路由设置中没有no deleteputrequest,因此例如,如果您将put请求发送到url,它将以405响应您Method Not Allowed

{
    "detail": "Method \"PUT\" not allowed."
}

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.