본문 바로가기
Python/Django

[DRF] permission_classes = [A, B]와 [A & B]의 차이

by 코드뭉치 2023. 6. 21.

1️⃣ 선요약

permission_classes = [A, B]

permission_classes = [A & B]

결과적으로 둘은 거의 같다. 그러나 실행 방식에 차이가 있고,

상황에 따라 다르지만, 논리곱(AND)연산만을 수행할 경우,

[A, B]의 방식이 일반적으로 조금 더 이점이 있다.

 

단, 두 조건을 중첩해서 OR과 비교할 경우(괄호를 통한 우선순위가 필요하다면),

&를 사용하는 것에 이점이 있다.

 

 

2️⃣ comma(,)를 사용했을 때

 

DRF의 .check_permissions(…) 메서드를 확인해보자.

def check_permissions(self, request):
    """
    Check if the request should be permitted.
    Raises an appropriate exception if the request is not permitted.
    """
    for permission in self.get_permissions():
        if not permission.has_permission(request, self):
            self.permission_denied(
                request,
                message=getattr(permission, 'message', None),
                code=getattr(permission, 'code', None),
            )

해당 메서드에서 리스트의 항목을 하나씩 돌면서 권한 중 하나가 실패하면,

실패한 권한의 메시지와 코드를 사용하여 .permission_denied(…) 메서드를 호출한다.

 

 

3️⃣ & 연산자를 사용했을 때

 

반면에 & 연산자를 사용하면 .and 메서드를 사용하여 새 permission을 생성한다.

DRF의 and 연산자를 확인해보자.

class OperationHolderMixin:
    def __and__(self, other):
        return OperandHolder(AND, self, other)


# …


class OperandHolder(OperationHolderMixin):
    def __init__(self, operator_class, op1_class, op2_class):
        self.operator_class = operator_class
        self.op1_class = op1_class
        self.op2_class = op2_class

    def __call__(self, *args, **kwargs):
        op1 = self.op1_class(*args, **kwargs)
        op2 = self.op2_class(*args, **kwargs)
        return self.operator_class(op1, op2)

    # …


class AND:
    def __init__(self, op1, op2):
        self.op1 = op1
        self.op2 = op2

    def has_permission(self, request, view):
        return self.op1.has_permission(request, view) and self.op2.has_permission(
            request, view
        )

    def has_object_permission(self, request, view, obj):
        return self.op1.has_object_permission(
            request, view, obj
        ) and self.op2.has_object_permission(request, view, obj)

 

 

4️⃣ 차이점

 

따라서 이것은 본질적으로 첫 번째 피연산자에서 .has_permission(…)을 먼저 실행하고,

성공하면 두 번째 피연산자에서 실행하기 위한  meta-programming logic일 뿐이다.

 


5️⃣ 결론

 

그래서 두가지 방식은 동일한가?

 

정확히는 아니다.

 

& 연산자를 사용하면 messagecode가 사라지므로,

어떤 permission이 거부되었는지 정확히 추적할 수 없다.

 

기본 제공 permission messagecode가 없지만,

custom permission에 사용자가 직접 지정하고, view에서 사용했을 때,

해당 코드는 codemessage를 반환하지 않는다.


따라서 작은 디테일이지만 permission에 대해서 &연산만을 수행할 경우,

[A ,B]를 사용하는 것이 [A & B]에 비해 약간의 이점이 있다.

 

그러나 두 조건을 중첩해서 OR과 비교할 경우, &연산자의 경우 괄호를 사용하여 처리가 가능하나,

쉼표의 경우 구분자로 작동하기 때문에 괄호 안에 쓸 수 없다.

 

permission_classes = [(A & B) | C] # O

permission_classes = [(A , B) | C] # X

 

아래의 경우,

(A, B) or (C, D) 가 아니라

A, (B or C), D 로 작동한다.

permission_classes = [A, B | C, D] # A / B또는C / D

 

따라서 논리 연산 사용 시, 괄호를 통한 우선순위가 필요하다면, &를 쓰는 것이 유리하다고 할 수 있다.

 

'Python > Django' 카테고리의 다른 글

[Django] fixtures  (0) 2023.06.22
[Django] bulk_create  (0) 2023.06.16
[DRF] Permissions  (0) 2023.06.10
[DRF] GenericAPIView와 Mixins  (0) 2023.06.07
[DRF] ModelSerializer와 CreateModelMixin 사용하기  (0) 2023.06.06

댓글