본 포스팅은 아래 링크의 내용을 나름대로 정리한 글이다.
https://www.django-rest-framework.org/tutorial/3-class-based-views/
1. REST API 뷰 정의하기 (APIView 클래스 이용)
이번에는 DRF가 제공하는 APIView 클래스를 이용하여 우리가 작성한 뷰들을 클래스 기반의 뷰들로 리팩토링 해보자. 각 메소드의 동작을 함수 단위로 보기 좋게 분리하였음을 볼 수 있다.
▼ snippets/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):
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)
class SnippetDetail(APIView):
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)
2. REST API 뷰 정의하기 (mixin 클래스 이용)
우리가 지금까지 뷰에 정의한 List, Create, Retrieve, Update, Delete의 기능들은 어떠한 백 엔드 애플리케이션의 API 뷰에서도 자주 사용이 되는 것들이다. 따라서 그러한 공통의 기능들은 DRF가 mixin 클래스들을 통해 이미 정의를 해놓았다. 다음은 DRF가 제공하는 mixin 클래스들을 활용하여 우리가 정의한 뷰들을 리팩토링 한 결과이다.
▼ snippets/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)
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 클래스를 상속함으로써 REST API 뷰로서의 핵심 기능을 상속받고, 각 동작(List, Create, Retrieve, Update, Delete)에 해당하는 mixin 클래스를 추가로 상속함으로써 해당 동작을 정의할 수 있게 되었다. 우리가 작성해줘야 하는 부분은 오로지 각 메소드에 해당하는 함수에 이미 구현되어 있는 해당 동작들을 연결해주는 것뿐이다.
3. REST API 뷰 정의하기 (mixed-in generic 클래스 이용)
놀랍게도 여기서도 한 단계 더 나아가 뷰를 간소화할 수 있는 방법이 있다. 우리가 정의한 뷰를 보면 List와 Create가 하나의 뷰로, 그리고 나머지가 하나의 뷰로 정의되어 있음을 알 수 있다. 이는 실제로 자주 사용되는 패턴이며, 따라서 DRF가 이러한 뷰의 작성을 위한 클래스들도 별도로 마련해놓았다. 이를 활용하여 우리가 정의한 뷰들을 또다시 리팩토링 해보자. 말도 안 되게 간결해진 것을 볼 수 있다.
▼ snippets/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
4. 마무리의 말
지금까지 DRF의 기능을 활용하여 간편하게 REST API 뷰를 정의하는 법을 알아보았다. 다음 포스팅에서는 로그인을 통한 유저의 권한 인증과 각 API의 접근에 대한 권한을 통제하는 방법에 대해 다뤄보도록 하자.
'장고 (Django)' 카테고리의 다른 글
[Django] 쿠키 및 세션 다루기 (+ messages, request.user) (0) | 2020.07.07 |
---|---|
[Django] REST framework - ④ Authentication & Permissions (2) | 2020.06.27 |
[Django] REST framework - ② Requests and Responses (0) | 2020.06.26 |
[Django] REST framework - ① Serialization (10) | 2020.06.26 |
[Django] REST API, Django REST framework (DRF) (4) | 2020.06.26 |