티스토리 뷰

서론

Django Restframework에서 편의를 위해 사용하는 ViewSet에서 서로 다른 permission을 적용하는 방법을 소개합니다.

본론

get_permission()

ViewSet 클래스의 메소드 중 get_permission(self)에서는 액션을 수행하기 전 사용할 permission들을 permission_classes에서 가져오는 메소드입니다.

    def get_permissions(self):
        """
        Instantiates and returns the list of permissions that this view requires.
        """
        return [permission() for permission in self.permission_classes]

그래서 해당 메소드를 오버라이딩해서 액션(action)별로 permission을 부여할 수 있습니다.
아래는 ReadOnlyModelViewSet에서 해당 메소드를 오버라이딩해서 retrieve 액션에만 다른 permission을 적용하는 방법입니다.

from rest_framework import viewsets

class UserViewSet(viewsets.ReadOnlyModelViewSet):
    """유저 리스트 혹은 개별 유저 데이터 반환
    """    
    queryset = get_user_model().objects.all()
    serializer_class = UserSerializer
    permission_classes = [IsAdminOrReadOnly]

    def get_permissions(self):
        if self.action == 'retrieve':
            # permission들은 class이기 때문에 ()로 객체 생성 후 전달
            return [IsAuthenticated(), IsAdminOrOwner()]
        return super().get_permissions()

BasePermission

또한 action에 적용할 사용자 정의 Permission을 만드는 방법입니다.
위에 나온 isAdminOrReadOnly나 IsAdminOrOwner의 경우에는 사용자 정의 permission입니다.
이들은 rest_framework.permissions.BasePermission을 상속받아 만들 수 있습니다.

class BasePermission(metaclass=BasePermissionMetaclass):
    """
    A base class from which all permission classes should inherit.
    """

    def has_permission(self, request, view):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return True

    def has_object_permission(self, request, view, obj):
        """
        Return `True` if permission is granted, `False` otherwise.
        """
        return True

주의할 점은 action에 따라 permission을 확인할 때 has_permission 메소드를 사용하는 action이 있고, 특정 레코드를 가져와야 할 때 사용하는 has_object_permission 메소드를 사용하는 경우가 있습니다. 따라서 경우에 따라 두 가지를 모두 오버라이딩 하거나 하나만 오버라이딩하여 사용자 정의 permission을 작성할 수 있습니다.

class IsAdminOrReadOnly(BasePermission):
    """User가 superuser일 때만 list 액션 허용
    """    
    def has_permission(self, request, view):
        if view.action == 'list':
            return request.user and request.user.is_superuser


class IsAdminOrOwner(BasePermission):
    """user가 superuser이거나 본인일때만 retrieve 액션 허용
    """    
    def has_object_permission(self, request, view, obj):
        return request.user and (request.user.is_superuser or obj == request.user)

결과

list 조회 시


일반 유저가 조회 시 위와 같이 권한 에러가 발생합니다.

superuser가 조회 시 위와 같이 모든 데이터가 반환됩니다.

retreive 조회 시


일반 유저가 본인이 아닌 유저를 조회하려고 할 때 권한 에러가 발생합니다.

결론

viewset의 메소드들을 잘 오버라이딩해서 사용하면 쉽게 구현할 수 있습니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/11   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30
글 보관함