티스토리 뷰
서론
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의 메소드들을 잘 오버라이딩해서 사용하면 쉽게 구현할 수 있습니다.
'개발자 > 파이썬(Python)' 카테고리의 다른 글
| [Pytorch] Docker를 이용해 Jupyter 서버 만들기 (0) | 2024.06.14 |
|---|---|
| [Django] 특정 쿼리셋만 Serialize하기 (0) | 2024.02.29 |
| [Django] DRF로 Token 로그인 구현 (0) | 2024.02.16 |
| [Python] Re 패키지로 정규표현식 사용하기 (0) | 2024.02.03 |
| [Django] Docker 배포 시 CSRF 검증에 실패했습니다. 해결방법 (0) | 2024.01.22 |
