이번 포스팅에서는 DRF의 Class-based Views 공식 문서를 공부하면서 번역해보려고 한다.
해석에 틀린 내용이 있을 수 있으니 이해가 안가는 부분은 아래의 공식문서를 참조하기 바란다.
DRF Class-based Views tutorial 공식 Documentation
함수 기반 뷰가 아닌 클래스 기반 뷰를 이용하여 API View를 작성할 수도 있다. 보시다시피 이것은 일반적인 기능을 재사용하고
코드를 DRY 하게 유지하는데 도움이 되는 강력한 패턴이다.
Rewriting our API using class-based views
루트 view를 클래스 기반 뷰로 재 작성할 것이다. 아래는 views.py 를 약간 리팩토링 한 것이다.
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
class SnippetList(APIView):
"""
코드 snippet의 목록을 보여주거나, 새로 snippet 생성
"""
def get(self, request, format=None):
snippets = Snippet.objects.all()
serializer = SnippetSerializer(snippets, many=True)
return Response(serializer.data)
def post(self, request, format=None):
serializer = SnippetSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
잘 진행되고 있다. 이전의 경우와 매우 비슷하게 보이지만 다른 HTTP methods를 더 잘 구분하였다.
또한 views.py에서 instance view(SnippetDetail)도 업데이트 해야 한다.
class SnippetDetail(APIView):
"""
snippet을 검색, 업데이트, 삭제
"""
def get_object(self, pk):
try:
return Snippet.objects.get(pk=pk)
except Snippet.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet)
return Response(serializer.data)
def put(self, request, pk, format=None):
snippet = self.get_object(pk)
serializer = SnippetSerializer(snippet, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
def delete(self, request, pk, format=None):
snippet = self.get_object(pk)
snippet.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
좋아 보인다. 또한 이것은 여전히 함수 기반 뷰와 매우 유사하다.
클래스 기반 뷰를 사용하고 있으므로 snippets/urls.py 를 약간 리팩토링해야 한다.
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views
urlpatterns = [
path('snippets/', views.SnippetList.as_view()),
path('snippets/<int:pk>/', views.SnippetDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
좋아 끝났다. 서버를 실행시키면 이전과 같이 잘 작동하는 것을 확인할 수 있다.
Using mixins
클래스 기반 뷰 사용의 가장 큰 장점중 하나는 재사용이 쉽게 가능하다는 것이다.
지금까지 사용한 Create/Retrieve/Update/Delete 명령은 일반적으로 모델을 사용할 때의 뷰와 비슷하다.
이러한 일반적인 동작은 REST framework에서 Mixin 클래스로 구현되어있다.
Mixin 클래스를 사용하여 구성하는 방법을 알아볼 것이다. views.py 모듈에서 살펴보자.
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import mixins
from rest_framework import generics
class SnippetList(mixins.ListModelMixin,
mixins.CreateModelMixin,
generics.GenericAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
def get(self, request, *args, **kwargs):
return self.list(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
return self.create(request, *args, **kwargs)
위에서 정확히 무슨일이 일어나는지 살펴보자.
GenericAPIView를 사용하여 뷰를 작성하고, ListModeMixin과 CreateModeMixin을 추가하였다.
GenericApiView는 핵심 기능을 제공하고 Mixin 클래스는 .list() 와 .create() 기능을 제공한다.
그런 다음 이 기능들을 get 과 post 메서드에 명시적으로 연결하였다. 아주 간단하다.
class SnippetDetail(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
generics.GenericAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
def get(self, request, *args, **kwargs):
return self.retrieve(request, *args, **kwargs)
def put(self, request, *args, **kwargs):
return self.update(request, *args, **kwargs)
def delete(self, request, *args, **kwargs):
return self.destroy(request, *args, **kwargs)
비슷하게 여기서도 GenericAPIView는 핵심 기능을 제공하고 나머지 Mixin들이 .retrive(), .update(), .destroy() 와 같은 기능을 제공한다.
Using generic class-based views
Mixin 클래스를 사용하여 이전의 코드에 비해 양이 줄어들었지만, 다음 과정을 진행하면 더 줄일 수 있다. REST framework는 이미 mixin과 Generic View를 결합한 것을 제공한다. 이를 사용하면 views.py 내용을 더 줄일 수 있다.
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer
from rest_framework import generics
class SnippetList(generics.ListCreateAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
class SnippetDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Snippet.objects.all()
serializer_class = SnippetSerializer
코드가 굉장히 간결해졌다. 큰 노력을 들이지 않고 많은 기능을 구현하였는데 코드는 Django 답게 깔끔해졌다.
tutorial part 4 에서는 API에서 인증과 권한을 어떻게 다루는 지 살펴볼 것이다.
'SW개발 > Django' 카테고리의 다른 글
[Django]Django REST Framework 튜토리얼 5 (Relationships & Hyperlinked APIs) (0) | 2021.03.31 |
---|---|
[Django]Django REST Framework 튜토리얼 4 (Authentication & Permissions) (0) | 2021.03.26 |
[Django]Django REST Framework 튜토리얼 2 (Requests and Responses) (0) | 2021.03.15 |
[Django]Django REST Framework 튜토리얼 1 (Serialization) (5) | 2021.03.09 |
[Django]Django REST Framework 튜토리얼 (Quickstart) (0) | 2021.03.07 |