티스토리 뷰

서론

클래스 기반 뷰에서 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'

결론

모든 일에는 순서가 중요한 것 같습니다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/07   »
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 31
글 보관함