사용자는 function based view뿐만 아니라 class-based view
를 사용하여 API를 작성할 수도 있다.
그럼으로써, class-based view
가 공통의 기능을 재사용하도록 허용해주는 강력한 패턴과, 사용자가 DRY(Do not repeat yourself)
하지 않도록 도와주는 것을 확인할 것이다.
views.py
를 열어 기존의 view를 class-based view로 리팩토링 해보자.
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):
"""
List all snippets, or create a new 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 메소드 간에 훨씬 나은 구별이 가능해졌다.
views.py
의 instance view 또한 업데이트 해주어야 한다.
class SnippetDetail(APIView):
"""
Retrieve, update or delete a snippet instance.
"""
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)
아직까지도 function based view와 많이 다르지는 않다.
snippets/urls.py
를 열어 class-based view에 맞게 url을 리팩토링 하자.
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)
여기서 runserver
를 돌려 모든 것이 정삭적으로 돌아간다면 다음 단계로 넘어가보자.
class-based view를 사용함으로써 얻는 큰 이점 중 하나가 쉽게 재사용 가능한 코드의 행동을 작성할 수 있다는 것이다.
지금까지 사용했던 create/retrieve/update/delete 방식과 매우 비슷한 방법들을 방금 생성한 model-backed API에서도 사용하게 될 것이다. 이런 공통의 행동들이 REST Framework의 mixin classs안에서 시행된다.
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)