ViewSet, django-rest-framework에서 메서드 비활성화


124

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)

답변:


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):
    ...

이 접근 방식을 사용하면 라우터는 포함 된 방법에 대한 경로 만 생성해야합니다.

참조 :

ModelViewSet


@SunnySydeUp 지금 시도하고 라우터가 목록보기에 대한 경로를 생성하는 것 같지만 ViewSet이 요청을 처리하는 방법을 모르기 때문에 404입니다. 이것이 당신이 기대했던 것입니까?
Steve Jalim 2014-07-31

3
필요한 믹스 인 만 사용하면 GET, POST, PUT, DELETE 메서드를 비활성화 할 수 있지만 라우터를 사용하는 경우 특별히 PATCH 메서드를 비활성화하는 방법을 찾을 수 없었습니다.
Muneeb Ahmad 2015

3
@MuneebAhmad PATCH 메서드는 UpdateModelMixin. 업데이트를 사용하고 싶지만 패치는 사용하지 않으려면 현재 두 가지 방법을 생각할 수 있습니다. 뷰에서 허용 된 메서드를 재정의하고 "패치"를 제거하거나 partial_update메서드를 재정의하고을 호출 할 수 있습니다 http_method_not_allowed(request, *args, **kwargs). 나는 이것을 테스트하지 않았기 때문에 그것이 작동하는지 확실하지 않다
SunnySydeUp

1
@JulioMarins 참조를 추가했습니다. 그래도 이것이 당신이 원하는 것인지 잘 모르겠습니다.
SunnySydeUp

1
누군가 읽기 전용 뷰셋을 만들고 싶다면 class SampleViewSet(viewsets.ReadOnlyModelViewSet).
Bikash kharel

133

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']

당신이 추가하면 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] :이 답변이 도움이 되었으면 https://www.agiliq.com/blog/2019/04/drf-polls/ 에서 DRF에 대한 내 게시물 시리즈를 좋아할 것입니다 .


16
이 방법의 문제는 목록이나 검색을 비활성화하는 방법이 아닙니다. 둘 다 비활성화하거나 둘 다 비활성화해야 함
Fuad

1
이것은 나를 위해 작동하지 않았습니다. get과 head를 포함한 후에도 여전히 게시물을 할 수있었습니다.
RunLoop

이것은 django 1.9에서 나를 위해 작동합니다. 훌륭한 솔루션입니다. 사용자가 다른 방법으로 GET 요청을 할 수있는 위험이 있습니까?
Ycon 2016

환상적인 솔루션. 에서 작동 python3하고 Django 1.10잘.
Urda

2
나는 PATCH를 포함하도록 mixin의 상속을 변경할 수 없기 때문에이 접근 방식을 선호하지만 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가 더 적절할 것이라고 생각합니다.
Santiago Magariños

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 내에서 올바르게 구현되지 않았기 때문에 여기에 설명 된 방식으로 전역 적으로 제거하는 것이 현명 할 것입니다
oden

1

DRF에서 ViewSet에 대한 "DELETE"메서드를 비활성화하는 방법

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 등의 중요한 메소드를 잊어 버릴 가능성이 적습니다.

기본적으로 PPS DRF는 http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']


super수업 수준에서 전화 를 걸 수 없습니다 self.
validname

0

Django Rest Framework 3.xx ModelViewSet에서는 사전을 as_view메서드 에 전달하여 활성화하려는 모든 메서드를 간단히 활성화 할 수 있습니다 . 이 사전에서 키는 요청 유형 (GET, POST, DELETE 등)을 포함해야하며 값은 해당 메소드 이름 (목록, 검색, 업데이트 등)을 포함해야합니다. 예를 들어 Sample모델을 만들거나 읽지 만 수정하고 싶지 않다고 가정 해 보겠습니다 . 당신이 원하는 의미 그래서 list, retrievecreate방법은 활성화 될 (그리고 당신이 비활성화로 다른 사람을 원한다.)

urlpatterns다음과 같은 경로를 추가하기 만하면됩니다 .

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

보시다시피 위의 라우팅 설정 에는 no deleteand putrequest가 없으므로 예를 들어 putURL에 요청을 보내면 405로 응답합니다 Method Not Allowed.

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.