Rest framework는 개발자가 state와 API의 interaction을 모델링하는데 더 집중할 수 있도록, 그리고 URL 구조가 공통의 컨션을 기반으로 자동적으로 다뤄지도록 허용해주는 ViewSets를 다루는 추상화를 포함한다.

ViewSet 클래스는 retrieveupdate 같은 기능, 그리고 get이나 put같은 핸들러 메소드를 제공한다는 점을 제외하고는 View 클래스와 거의 같다고 할 수 있다.

ViewSet 클래스가 뷰의 집합으로 인스턴스화 되었을 때만 오직 마지막 순간에 핸들러 메소드의 집합에만 바운딩 된다. 일반적으로 URL conf를 정의하는데의 복잡함을 다루는 Router 클래스를 사용한다.

ViewSets를 사용해서 리팩토링하기


ViewSets를 이용해서 UserListUserDetail 뷰를 단일의 UserViewSet으로 리팩토링 해줄 수 있다.

from rest_framework import viewsets

class UserViewSet(viewsets.ReadOnlyModelViewSet):
    """
    This viewset automatically provides `list` and `retrieve` actions.
    """
    queryset = User.objects.all()
    serializer_class = UserSerializer

자동적으로 기본 'read-only' 작업을 제공하기위해 ReadOnlyModelViewSet이 사용되었다. 여전히 querysetserializer_class 속성들을 기존의 view에서 사용한 것처럼 설정한다. 하지만 같은 정보를 더 이상 두 별도의 클래스에 나누어 제공할 필요는 없어진다.

다음 예제에서는 SnippetList, SnippetDetail, 그리고 SnippetHighlight 뷰 클래스를 단일의 클래스로 만들어준다.

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import permissions

class SnippetViewSet(viewsets.ModelViewSet):
    """
    This viewset automatically provides `list`, `create`, `retrieve`,
    `update` and `destroy` actions.

    Additionally we also provide an extra `highlight` action.
    """
    queryset = Snippet.objects.all()
    serializer_class = SnippetSerializer
    permission_classes = [permissions.IsAuthenticatedOrReadOnly,
                          IsOwnerOrReadOnly]

    @action(detail=True, renderer_classes=[renderers.StaticHTMLRenderer])
    def highlight(self, request, *args, **kwargs):
        snippet = self.get_object()
        return Response(snippet.highlighted)

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user

이번 예제에서는 기본 읽기와 쓰기 작업의 완전한 집합을 얻기위해 ModelViewSet을 사용하였다.

그리고 highligt 라는 이름의 커스텀 액션을 생성하기 위한 @action 데코레이터도 쓰여졌다. 이 데코레이터는 표준 create/update/delete 스타일에 맞지 않는 어떤 커스텀 엔드포인트라도 추가하는데 사용될 수 있다.

@action 데코레이터를 사용하는 커스텀 액션은 기본적으로 GET 요청에 응답하게 된다. 만약 POST 요청에 응답하는 액션을 원한다면 methods 인자를 사용할 수 있다.

기본 커스텀 액션을 위한 URLs는 메소드 이름 자체를 의존한다. 만약 url이 세워지는 방법을 바꾸고 싶다면, url_path를 데코레이터 키워드 인수로 포함할 수 있다.

명백하게 ViewSets를 URLs에 바인딩하기


핸드럴 메소드는 오직 URLConf를 정의했을때만 액션에 바운딩 된다.