이 포스트는 인프런의 "Django REST Framework 핵심사항"강의를 듣고 제작하였습니다.
저번 포스트에서 DRF의 Router에 대해서 자세히 알아봤었다. 이번엔 GenericView의 기본적인 개념에 대해서 알아보도록 하겠다.
시작하기 전에 앞서 강의에서 보통은 ViewSet으로 테이블에 대한 CRUD Operation을 확인한 후에 GenericView로 상세하게 코딩을 하는 것이 좋다고 하였다.
이것에 대해서는 추후에 ViewSet까지 다루고 나서 얘기해 볼 예정이다.
Generic이란 단어의 뜻은 프로그래밍의 관점에서 보면 다음과 같다.
generic programming은 데이터 형식에 의존하지 않고, 하나의 값이 여러 다른 데이터 타입들을 가질 수 있는 기술에 중점을 두어 재사용성을 높일 수 있는 프로그래밍 방식이다.
-위키백과
즉, DRF의 GenericView도 같은 맥락이라고 생각 할 수 있을 것 같다.
웹페이지 안에서는 HTTP Method들이 복합적으로 결합되어 공통적으로 작동하는 기능들이 있다.
예를 들어서 글의 목록에 관한 동작, 글의 상세 페이지에 관한 동작이 이에 해당할 것이다.
그렇기 때문에 이런 공통적인 과정들을 클래스로 만들어 코드의 재사용성을 높이고 이를 통해 생산성을 높이는 것이 GenericView가 만들어진 목적이라고 볼 수 있다.
GenericView의 종류와 구조를 살펴보면 다음과 같다.
한 눈에 바로 알 수 있는 점이 바로
GenericView들은 동일한 파일에 존재하는 GenericAPIView와 Mixin클래스를 상속받아 만들어졌음을 알 수 있다.
이 중에 상위 5개의 클래스를 구체적으로 살펴보면 다음과 같이 되어있다.
각각의
GenericView안의 메소드는 HTTP Method로 정의되어 있으며 세부적으로는 다른 메소드들을 호출하고 그 결과를 반환하는 형식으로 되어있다. (list, retrieve 등등)
이에 대한 출처를 타고 들어가보면 이 메소드들은 해당 GenricView가 상속받은 Mixin클래스에 그에 대한 정의가 되어있음을 확인할 수 있다.
GenericAPIView는 실제로 모든 GenericView에 대한 Base클래스의 역할을 한다고 파일 내부에 적혀있으며 이를 살펴보면 다음과 같다.
각각의 속성과 메소드는
GenericView를 쓰던 ViewSet을 쓰던 알아야되는 내용이기 때문에 짚고 넘어가려고 한다.
공식문서를 참고하여 글을 작성하였다.
클래스의 Attibute는 다음과 같다.
GenericAPIView의 Attribute
queryset: 전달받은model의객체목록.model을 통해 만들어진 여러 개의객체들에 대한list
serializer_class: 해당queryset에 대해serializer를 할 때 사용할클래스
lookup_field:queryset의 각각의instance에 접근하기 위해 사용하는 model의Field,
Default로는테이블의pk이며model의 다른Field도 사용가능하다.
lookup_url_kwarg:URL을 통해서queryset의 각각의 객체에 접근할 때 사용되는 키워드이다.
Default로pk를 사용하며URLConf에 이 키워드가 반드시 포함되어 있어야 한다.
filter_backends:필터나검색을 할 때 사용할 엔진
pagination_class:페이지기능을 사용하기 위해 사용할클래스
여기서 특히 눈여겨 봐야 할 속성은 queryset과 serializer_class이다. 기본적으로 이 속성은 GenericView 혹은 ViewSet을 쓸 때의 대부분의 상황에서 정의되어야 하는 내용이다.
이제 GenericAPIView의 메소드들 대해서 알아보자.
GenericAPIView의 주요 Method
get_queryset(self):List를 보여주는View,detail을 보여줄 때 사용할View에 사용할queryset을 반환한다.Default로는 클래스에서 정의된queryset이다.
get_object(self):detail의View에서 사용되는queryset의object를 반환한다.
둘 이상의URLKwarg를 가지고 있는 경우와 같이 복잡한 동작을 실행하도록 오버라이딩할 수 있다.
get_serializer_class(self):serializer_class를 반환하는 메소드.
이것을 오버라이딩하여 각각의 다른 동작에 대해서 다르게serializer_class를 지정해줄 수 있다.
GenericAPIView의 기타 Method
get_serializer(self, *args, **kwargs):serialize된instance를 제공하는 메소드.
기본적으로는serializer_class에서 지정한 클래스로serialize된다.
get_serializer_context(self):serializer의 형태를 지정하는 메소드. 마찬가지로 오버라이딩을 통해 바꿀 수 있다.
filter_quertset(self, queryset): 앞서 지정된filter_backends를 이용하여filtering된queryset을 반환하는 메소드. 오버라이딩 할 일은 많이 없다.
paginating관련 메소드
paginator(self),paginate_queryset(self, queryset),get_paginated_response(self, data)
모든 메소드들이 중요하지만 특히 주요메소드 3가지는 프로젝트를 할 때마다 오버라이딩을 하는 경우가 많았기 때문에 어떤 메소드인지는 분명히 알고 가는 것이 좋다.
예를 들어, 검색이나 필터관련 기능을 구현할 때 좀 더 복잡한 기능을 위해 filter_backends를 지정해서 사용하는 대신 get_queryset을 오버라이딩하여 구현하는 경우도 많았다.
세부적인 메소드들에 대한 오버라이딩은 추후에 다뤄볼 예정이다.
이제 Mixin클래스들의 구조에 대해서 알아보자. 대부분 직관적이기 때문에 어떤 기능을 유추하는지도 알기 쉽다.
이 클래스들은 GenericView의 Http Method로 정의되어 있는 메소드들에 대한 실제 내용이 담겨져있다.
위를 확인해보면 기본적인
HTTP method를 포함한 여러 동작들이 각각 다른 이름으로 정의되어있다.
이를 정리해보면 다음과 같다.
| DRF Action | HTTP Method |
|---|---|
| Create | POST |
| Update | PUT |
| Partial_update | PATCH |
| Destroy | DELETE |
| List | GET |
| Retrieve | GET |
특이한 점은 GET요청이 queryset의 전체 목록에 대한 List와 그 중 하나의 instance를 나타내는 Retrieve
두 개로 구분되어 있다는 점이다.
또한 위와 같이 접두사로 perform_이 들어가 있는 메소드는 serialize된 데이터를 저장하는 부분을 따로 떼어서 만든 메소드이다.
개발자는 이 부분만 오버라이딩함으로써 Create와 Update같은 메소드를 좀 더 편하게 오버라이딩할 수 있다.
위에서 정리한 GenericAPIView와 Mixin클래스를 상속받아 만들어진 GenericView들은 다음과 같은 동작을 한다.
CreateAPIView:POST요청에 대해서 다룬다.
ListAPIView:queryset의 리스트를 제공하며GET요청을 다룬다. ( List )
RetrieveAPIView: 하나의instanceGET요청을 다룬다. ( Detail )
DestroyAPIView: 하나의instance에 대한Delete요청을 다룬다.
UpdateAPIView: 하나의instance에 대한Update요청을 다룬다.
ListCreateAPIView:ListAPIView+CreateAPIView
RetrieveUpdateAPIView:RetrieveAPIView+UpdateAPIView
RetrieveDestoryAPIVew:RetrieveAPIView+DestroyAPIView
RetrieveUpdateDestroyAPIView:RetrieveAPIView+UpdateAPIView+DestroyAPIView
DRF의GenericView들은GenericAPTView와 여러Mixin클래스를 상속받아 만들어졌다.
GenericAPIView에는GenericView들에 대해 전반적으로 사용되는attribute와method들이 정의되어 있다.
Mixin클래스에는GenricView들 각각에 정의된HTTP Method들에 대한 정의가 들어있다.
이번 글은 GenercView에 대해서 직접 응용하여 코딩을 하기 전에 개념적인 측면을 살펴보고자 작성하였다. 강의에서 간략하게 다뤘던 내용들에 대해서 공식문서와 여러 포스트들을 참고하여 내용을 정리해보았다.