[python] ViewSet, 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)



답변

정의 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


답변

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에 대한 내 게시물 시리즈를 좋아할 것입니다 .


답변

이 게시물은 오래되었지만 실제로는 이러한 기능을 비활성화하는 방법이라는 것을 갑자기 발견했습니다. 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)


답변

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


답변

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."
}


답변

put / post / destroy 메서드를 비활성화하려는 경우 다음을 사용할 수 있습니다.

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