Python/Django

Django Rest Framework ViewSet

DevelopC 2022. 9. 28. 18:40
728x90

Django Rest Framework ViewSet

  • Django Rest Framework의 ViewSet에 대하여 설명합니다.
  • Django에서는 View 개념이 있습니다. 응답을 받아 처리 후 리턴하는 방식으로 컨트롤러 역할을 합니다.
  • 함수 형태(FBV)로 작성하거나 클래스 형태(CBV)로 작성합니다.
  • Django를 이용해 웹 서비스를 만들 때 RESTful 조건에 맞게 만들기 위하여 Django Rest Framework를 사용합니다.
  • Django Rest Framework를 이용한 Class based view 인 Model ViewSet에 대하여 이해합니다.

ViewSet이란?

  • Django Rest Framework에서 HTTP Request/Response를 처리할 때 메서드 단위 또는 클래스 단위로 구현합니다.
  • 다른 언어의 프레임워크에서 Controller에 해당한다고 보면 됩니다.
  • Function에 비해 조금 더 많은 학습이 필요한 Class 형태로 뷰를 만드는 이유가 뭘까?
    • 일반적으로 프로그래밍에서 Function대신 Class를 사용하는 것과 같은 이유이다. 
    • 추상화, 상속, 인터페이스 구현 등 OOP 기법을 통해 개발함으로써 중복 코드를 만들지 않고 유지 보수에 이점이 있기 때문이다.
# function based
@api_view(['GET', 'POST'])
def book_info(request, book_no, **kwargs):
    if request.method == 'GET':
        return Response(data={"result_date": "response body 입니다"}, status=status.HTTP_200_OK) 
    else:
        return Response(status=status.HTTP_200_OK) 


# class based
class Book(View):
    def post(self, request):
        return Response(status=status.HTTP_200_OK) 
    
    def get(self, request):
        return Response({"result_date": "response body 입니다"}, status=status.HTTP_200_OK)

Django Rest Framework의 ViewSet 관련 구성 요소

  • ViewSet: APIView에서 상속받는 기본 뷰셋으로 API 권한 제어를 위한 permission_classes와 authentication_classes 만을 사용한다. 액션은 명시적으로 정의해야 한다.
  • Generic ViewSet: GenericAPIView를 상속하며 ViewSet 이 제공받는 권한 제어와 함께 get_object, get_queryset, get_serializer_class을 제공받고 기본 동작 셋은 있으나 그 외 액션은 명시적으로 정의해야 한다.
  • Model ViewSet: GenericAPIView를 상속하며 다양한 Generic ViewSet의 기능과 함께. list(), retrieve(), destroy(), update(), partial_update(), create()를 제공받는다. 별도 추가 구현 없이도 해당 메서드들 사용 가능. queryset과 serializer_class를 반드시 정의해야 한다.

queryset

Model ViewSet을 상속할 때 반드시 구현해야 하는 구성 요소로, 해당 뷰셋과 연관된 모델 클래스를 정의해주어야 한다. 

class MemberViewSet(ModelViewSet):
    """
    회원 정보 뷰셋
    """
    queryset = Member.objects.all()

permission_classes

  • 권한 제어를 위한 클래스를 선언합니다.
  • Django Rest Framework에서는 권한 체크를 위한 클래스를 커스터마이징 할 수 있는데 용도에 맞게 여러 권한 체크하는 클래스를 만든 후 해당 뷰셋에서 필요한 권한을 추가하는 방법으로 사용한다.
  • permissions 클래스는 IsAuthenticated 나 BasePermission과 같은 DRF 제공 클래스를 상속받은 후 True/False를 리턴하는 has_permission이라는 메서드를 오버라이드 해주면 되는데, 메서드에 전달되는 인자에는 request와 view가 있다.
class IsAuthenticatedPermission(IsAuthenticated):
    """
    login user
    """
    def has_permission(self, request, view):
        if is_login_user():
            return True
        return False

class AllowIPPermission(permissions.BasePermission):
    """
    allow ip
    """
    allow_ip = ['10.10.10.0', ]

    def has_permission(self, request, view):
        ip_addr = request.META['REMOTE_ADDR']
        return ip_addr in AllowIPPermission.allow_ip

class MemberViewSetLogin(ModelViewSet):
    # login 유저만 사용할 수 있는 뷰셋
    permission_classes = (IsAuthenticatedPermission,) 
 
class MemberViewSetAllowIp(ModelViewSet):
    # login 유저이면서 특정 ip 유저만 사용 가능한 뷰셋
    permission_classes = (IsAuthenticatedPermission, AllowIPPermission)

get_queryset

뷰셋의 연관 모델을 queryset에 정의하는데, 추가적으로 filter를 통해 데이터 범위를 좁히거나 query join을 처리하고자 할 때 get_queryset 메서드에서 처리할 수 있다.

# 조인 추가 
def get_queryset(self):
    return Book.objects.select_related('member_no').all()

# 필터 적용 
def get_queryset(self):
    queryset = Book.objects.all()
    if self.request.member_no:
        queryset = queryset.filter(member_no=self.request.member_no)

    return queryset

get_serializer_class

# 기본 선언 
def get_serializer_class(self):
    return MemberSerializer

# HTTP Request Method에 따른 분기 
def get_serializer_class(self):
    if self.action == 'create':
        return CreateMemberSerializer

    if self.action == 'list':
        return ReadOnlyMemberSerializer

    if self.action in ('update', 'partial_update'):
        if self.request.member_no:
            return UpdateMemberSerializerWithMemberNo
        else:
            return UpdateMemberSerializer

retrieve, list, create, destroy, update, partial_update

  • Django Rest framework Model ViewSet 상속받을 경우 기본으로 제공되는 메서드입니다.
    • create - POST /
    • list - GET /
    • retrieve - GET /<pk>
    • update - PUT /<pk>
    • partial_update - PATCH /<pk>
    • destroy - DELETE /<pk>

get_serializer_context

뷰셋은 MVC 패턴의 컨트롤러 역할을 한다.  요청을 받아 모델과 뷰를 연결해 처리된 결과를 리턴한다. 이때 주요 비지니스 로직이 아닌 것들은 최대한 알아서 처리하여 넘겨주게 된다.  예를 들어 게시판 리스트를 리턴하는 API에서 DB를 연결맺고, Http Request 를 받아 쿠키를 파싱하고 세션을 처리하고 그에 맞는 권한 처리를 한다거나, 비지니스 로직에서 참조해야 하는 유저 정보를 세팅하는 등의 일은 주요 비지니스 로직은 아니다. 게시판 리스트의 주요 비지니스 로직은 게시물 데이터를 파싱하고 필요하다면 가공한 후 json 을 리턴하는 것이 될 것이다. Django Rest Framework에서 ViewSet을 구현하면 뷰셋 선언에 따라 권한을 처리하고 회원 정보를 파싱 하는 등의 작업을 쉽게 처리할 수 있다.  ViewSet이 model 객체와 로직을 연결할 때 serializer에게 data 만을 전달하는데, ViewSet이 처리한 권한이나 회원 객체 등을 serializer 에게 전달하고 싶을 때 get_serializer_context 메서드에서 처리할 수 있다. 해당 메소드에 정의 한 값은 serializer 내 self.context [KEY]와 같은 식으로 접근할 수 있다.

# ViewSet에서 Serializer에게 전달할 값 선언
class MemberViewSet(ModelViewSet):
    def get_serializer_context(self):
        return {
            'member_no': self.request.member_no,
        }

# ViewSet에서 넘어온 값을 Serializer에서 사용
class MemberSerializer(ModelSerializer):
    def validate(self, data):
        print(self.context['member_no'])
728x90

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

Django Rest Framework Filter  (0) 2022.10.05
Django ORM  (2) 2022.09.23
Django Rest Framework Excel Renderer 클래스  (0) 2017.08.02
Django ORM기반 ERD 생성  (0) 2017.07.06