티스토리 뷰
서론
클래스 기반 뷰에서 UserPassesTestMixin
를 활용해 특정 조건일 때만 동작을 허용하도록 만드는 방법을 소개합니다.
본론
UserPassesTestMixIn
클래스 기반 뷰에서 클라이언트가 접근시에 사용자 정의 가능한 테스트를 추가할 수 있도록 해주는 MixIn입니다. 아래는 해당 MixIn의 코드입니다.
class UserPassesTestMixin(AccessMixin):
"""
Deny a request with a permission error if the test_func() method returns
False.
"""
def test_func(self):
raise NotImplementedError(
"{} is missing the implementation of the test_func() method.".format(
self.__class__.__name__
)
)
...
아래에 함수가 더 있지만 필요 없으므로 생략하고, 조건을 추가하기 위해서는 test_func
을 오버라이딩하면 됩니다.
test_func 오버라이딩
test_func에서 인자로 받는 self에서 request에 접근이 가능합니다. 그래서 user의 특정 조건에 따라 접근을 제어할 수도 있고, headers에 인증정보를 전달하고 싶다면 그렇게 해도 됩니다.
아래는 커스텀 조건을 추가하는 두 가지 예시를 소개합니다.
# superuser인 경우에만 통과하도록 하는 방법
class SuperuserRequiredMixin(UserPassesTestMixin):
"""관리자만 접근하도록 지정하는 믹스인
"""
def test_func(self):
return self.request.user.is_superuser
# HttpRequest Headers에 특정 값이 존재하는 경우에만 통과하도록 하는 방법
class AuthKeyRequiredMixin(UserPassesTestMixin):
"""headers에 auth-key가 존재하는지 여부 확인
"""
def test_func(self):
return self.request.headers.get('auth-key') == settings.AUTH_KEY
redirect 주소를 바꾸는 방법
UserPassesTestMixin은 AccessMixin을 상속받습니다. 그래서 테스트를 통과하지 못하면 로그인 페이지로 이동하게 됩니다. 그래서 페이지를 바꾸고 싶다면 login_url 속성을 오버라이딩 해주시면 됩니다.
class SuperuserRequiredMixin(UserPassesTestMixin):
"""관리자만 접근하도록 지정하는 믹스인
"""
# reverse_lazy 를 이용해 Django Template에서의 url처럼 사용 가능
login_url = reverse_lazy('home')
def test_func(self):
return self.request.user.is_superuser
API View에서 사용하기
뷰를 API로 사용하고 있다면 UserPassesTestMixIn을 통과하지 못할 때 login_url에 해당하는 HTML text가 전달되게 됩니다.
다른 Response를 전달하고 싶다면 handle_no_permission
을 오버라이딩하면 됩니다.
class AuthKeyRequiredMixin(UserPassesTestMixin):
"""headers에 auth-key가 존재하는지 여부 확인
"""
def test_func(self):
return self.request.headers.get('auth-key') == settings.AUTH_KEY
def handle_no_permission(self):
"""auth-key가 존재하지 않거나 일치하지 않을 경우 "You have not permission"로 reply
"""
return HttpResponse("You have not permission")
주의할 점
클래스 기반 뷰에서 Mixin을 상속받을 때에는 순서가 중요합니다. 어노테이션의 순서 때문에 필요한 조건의 순서에 따라 왼쪽부터 차례대로 mixin을 상속받아야 합니다.
class UserInfoView(SuperuserRequiredMixin, DetailView):
"""유저 정보를 제공하기 위한 클래스 기반 뷰
"""
model = get_user_model()
context_object_name = 'userInfo'
template_name = 'accounts/userInfo.html'
# 잘못된 예) DetailView를 먼저 상속하면 SuperuserRequiredMixin이 동작하지 않습니다!
class UserInfoView(DetailView, SuperuserRequiredMixin):
"""유저 정보를 제공하기 위한 클래스 기반 뷰
"""
model = get_user_model()
context_object_name = 'userInfo'
template_name = 'accounts/userInfo.html'
결론
모든 일에는 순서가 중요한 것 같습니다.
'개발자 > 파이썬(Python)' 카테고리의 다른 글
[Python] Re 패키지로 정규표현식 사용하기 (0) | 2024.02.03 |
---|---|
[Django] Docker 배포 시 CSRF 검증에 실패했습니다. 해결방법 (0) | 2024.01.22 |
[Django] Docker 컨테이너에서 createsuperuser 사용 (0) | 2024.01.17 |
[Django] Django와 MySQL 혹은 MariaDB Docker로 연결 (0) | 2024.01.17 |
[Django] Docker로 Django 배포하기 (0) | 2024.01.15 |