python - start - rest framework request




액션 당 Django rest-framework 권한 (4)

DRF 문서에서,

참고 : 인스턴스 수준의 has_object_permission 메소드는 뷰 수준의 has_permission 검사가 이미 통과 된 경우에만 호출됩니다.

user 객체에 대한 권한을 다음과 같이 가정 해 봅시다.

  • 목록 : 직원 전용
  • 만들기 : 모든 사용자
  • 검색 : 자신 또는 직원
  • 업데이트, 부분 업데이트 : 본인 또는 직원 소유
  • 폐기 : 직원 전용

permissons.py

from rest_framework import permissions

class UserPermission(permissions.BasePermission):

    def has_permission(self, request, view):
        if view.action == 'list':
            return request.user.is_authenticated() and request.user.is_admin
        elif view.action == 'create':
            return True
        elif view.action in ['retrieve', 'update', 'partial_update', 'destroy']:
            return True
        else:
            return False

    def has_object_permission(self, request, view, obj):
        # Deny actions on objects if the user is not authenticated
        if not request.user.is_authenticated():
            return False

        if view.action == 'retrieve':
            return obj == request.user or request.user.is_admin
        elif view.action in ['update', 'partial_update']:
            return obj == request.user or request.user.is_admin
        elif view.action == 'destroy':
            return request.user.is_admin
        else:
            return False

views.py

from .models import User
from .permissions import UserPermission
from .serializers import UserSerializer
from rest_framework import viewsets


class UserViewSet(viewsets.ModelViewSet):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = (UserPermission,)

편집하다

Django 2.0의 경우 is_authenticated()is_authenticatedis_authenticated . 메서드가 특성으로 바뀌 었습니다.

저는 Django + Django Rest-framework로 개발하는 초보자이고 REST API 액세스를 제공하는 프로젝트를 진행하고 있습니다. ApiView 또는 Viewset의 각 동작에 다른 권한을 할당하는 것이 가장 좋은 방법인지 궁금합니다.

'IsAdmin', 'IsRole1', 'IsRole2'등과 같은 일부 사용 권한 클래스를 정의하고 단일 작업에 다른 사용 권한을 부여하려고한다고 가정합니다 (예 : Role1을 가진 사용자는 다음과 같은 사용자를 만들거나 검색 할 수 있습니다. Role2는 업데이트 할 수 있으며 관리자 만 삭제할 수 있습니다).

'create', 'list', 'retrieve', 'update', 'delete'액션에 권한 클래스를 할당하기 위해 어떻게 클래스 기반 뷰를 구성 할 수 있습니까? 동일한 권한 패턴을 가진 여러 테이블에 대해 재사용 할 수있는 클래스를 갖기 위해 노력하고 있습니다.

어쩌면 물 한 방울에 물에 빠져있을 수도 있습니다. 답장을 보내 주셔서 감사합니다.


Django는 Django Guardian을 인증 백엔드로 사용하는 DjangoObjectPermissions라는 persmissions 클래스를 가지고 있습니다.

장고 보호자가 설정에 활성화되어 있으면 view에 permission_classes = [DjandoObjectPermissions] 를 추가하면 권한 인증이 자동으로 수행되므로 특정 django.contrib.auth 그룹 또는 사용자에게 설정된 권한을 기반으로 'CRUD'할 수 있습니다.

예를 들어 gist 을보십시오.

Django Guardian을 인증으로 설정할 수 있습니다. http://django-guardian.readthedocs.org/en/latest/installation.html


나는 개인적으로 frankenmonster 사용자 정의 권한이 이런 종류의 싫어, 제 의견으로는, 그것은 장고 프레임 워크에 있어서는 매우 관용적이지 않습니다; 그래서 다음과 같은 해결책을 @detail_route 습니다. @list_route@detail_route 데코레이터가 작동하는 것과 매우 흡사합니다. 우리는 메소드 / 함수가 퍼스트 클래스 객체라는 사실에 의지하고 있습니다.

우선 내가 그런 장식자를 만들고 있어요.

decorators.py

def route_action_arguments(**kwargs):
    """
    Add arguments to the action method
    """
    def decorator(func):
        func.route_action_kwargs = kwargs
        return func
    return decorator

보시다시피 arg list로 전달 된 매개 변수로 데코 레이팅하는 함수에 사전을 추가합니다.

이제는 믹스 인 mixins.py를 만들었습니다.

class RouteActionArgumentsMixin (object):
    """
    Use action specific parameters to 
    provide:
    - serializer
    - permissions
    """

    def _get_kwargs(self):
        action = getattr(self, 'action')
        if not action:
            raise AttributeError
        print('getting route kwargs for action:' + action)
        action_method = getattr(self, action)
        kwargs = getattr(action_method, 'route_action_kwargs')
        print(dir(kwargs))
        return kwargs

    def get_serializer_class(self):
        try:
            kwargs = self._get_kwargs()
            return kwargs['serializer']
        except (KeyError, AttributeError):
            return super(RouteActionArgumentsMixin, self).get_serializer_class()

    def get_permissions(self):
        try:
            kwargs = self._get_kwargs()
            return kwargs['permission_classes']
        except (KeyError, AttributeError):
            return super(RouteActionArgumentsMixin, self).get_permissions()

Mixin은 두 가지 작업을 수행합니다. get_permissions 가 호출 될 때 어떤 'action'이 실행되는지 확인하고 route_action_kwargs 와 연관된 route_action_kwargs에서 permission_classes 콜렉션을 viewset.action_method.route_action_kwargs

get_serializer_class 가 호출 될 때, 동일한 작업을 수행하고 route_action_kwargs 에서 serializer 를 선택합니다.

이제 우리가 사용할 수있는 방법 :

@method_decorator(route_action_arguments(serializer=LoginSerializer), name='create')
class UserViewSet (RouteActionArgumentsMixin, RequestContextMixin, viewsets.ModelViewSet):
    """
    User and profile managment viewset
    """

    queryset = User.objects.all()
    serializer_class = UserSerializer

    @list_route(methods=['post'])
    @route_action_arguments(permission_classes=(AllowAny,), serializer=LoginSerializer)
    def login(self, request):
        serializer = self.get_serializer_class()(data=request.data)

명시 적으로 정의한 커스텀 @route_action_arguments 경우, 메소드에 @route_action_arguments 명시 적으로 설정할 수 있습니다.

일반적인 뷰 세트 및 메소드의 측면에서 우리는 @method_decorator 사용하여 추가 할 수 있습니다

@method_decorator(route_action_arguments(serializer=LoginSerializer), name='create')
class UserViewSet (RouteActionArgumentsMixin, RequestContextMixin, viewsets.ModelViewSet):

DRF의 BasePermission 확장하는 사용자 정의 권한 클래스를 만들 수 있습니다.

requestview 객체에 대한 액세스 권한이있는 has_permission 구현합니다. request.user 에서 해당 역할을 확인하고 적절한 경우 True / False 를 리턴 할 수 있습니다.

얼마나 쉬운 지에 대한 좋은 예를 IsAuthenticatedOrReadOnly 제공된 IsAuthenticatedOrReadOnly 클래스 (및 다른 클래스)를 살펴보십시오.

도움이되기를 바랍니다.





django-permissions