함수 기반 View 가아닌 Class 기반 View를 사용해서 API View를 작성할 수도 있습니다.

여러분도 잘 알듯이 클래스기반 View는 일반적인 기능을 재사용 할수있는 강력한 패턴입니다. 그리고 코드의 유지를 훨씬 효율적으로 할수 있습니다.


[ 클래스 기반 View를 사용해서 다시 API를 작성해봅시다.]


먼저 Root View를 클래스 기반 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):
    """
    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메소드를 구분하기에 훨씬 쉽습니다. 


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)

Detail도 마찬가지로 함수뷰와 비슷하지만 보기에 훨씬 이뻐보입니다. 

클래스 기반 View를 사용하기 때문에 url.py를 살짝 리팩토링해야합니다.


from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views

urlpatterns = [
    url(r'^snippets/$', views.SnippetList.as_view()),
    url(r'^snippets/(?P<pk>[0-9]+)/$', views.SnippetDetail.as_view()),
]

urlpatterns = format_suffix_patterns(urlpatterns)

이제, 개발서버를 실행하면 모든 것이 이전과 같이 작동해야 합니다.


[ 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를 사용하고 ListModelMixin 및 CreateModelMixin 을 추가해서 뷰를 작성합니다.


베이스클래스는 핵심기능을 제공하고 mixin 클래스는 .list() 및 .create() 를 제공합니다.

그런다음 get및 post 메소드를 명시적으로 적절한 액션에 바인딩합니다. 


이전과 거의 비슷하지만. GenericAPIView 클래스를 사용해서 핵심 기능을 제공하고 .retrieve(), .update(), 및 .destroy() 액션을 제공하기 위해서 mixin 을 추가합니다.


[ 제네릭 클래스 기반 뷰 사용 ]


mixin 클래스를 사용해서 이전보다 적은 코드를 사용하기 위해 뷰를 새로작성했지만 좀더 나아가봅시다.


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

와.. 이번엔 진짜 간결합니다. 굉장히 코드는 훌륭하고 깨끗하며 관용적인 장고처럼 보입니다.



Posted by C마노
,