D.S

raccoonyy.github.io

DRF3 튜토리얼 6 - 뷰셋과 라우터

DRF3 튜토리얼 6 - 뷰셋과 라우터 Close Menu Home About Me Django Python Twitter Facebook Subscribe Menu DRF3 튜토리얼 6 - 뷰셋과 라우터 raccoony | 11 Mar 2015 원문 - Viewsets and Routers 번역을 허락해 준 Tom Christie 에게 고마움을 전합니다. 튜토리얼 6: 뷰셋 & 라우터 REST 프레임워크는 ViewSets이라는 추상 클래스를 제공합니다. 이를 통해 개발자는 API의 상호작용이나 상태별 모델링에 집중할 수 있고, URL 구조는 기본 관례에 따라 자동으로 설정됩니다. ViewSet 클래스는 View 클래스와 거의 비슷하지만, get과 put 메서드는 지원하지 않고 read와 update 메서드를 지원합니다. ViewSet 클래스는 따지고 보면, 앞 장에서 만든 핸들러 메서드가 실제 뷰로 구체화될 때 이를 연결해주기만 합니다. 이때 보통은 Router 클래스를 사용하여 복잡한 URL 설정을 처리합니다. 뷰셋을 사용하여 리팩터링하기 지금까지 만든 뷰들을 살펴보면서 뷰셋을 사용해서 리팩터링을 해봅시다. 가장 먼저 리팩터링할 뷰는 UserList와 UserDetail 뷰입니다. UserViewSet 하나로 모아보죠. 두 뷰의 코드를 삭제한 다음 아래의 클래스 하나를 입력합니다. from rest_framework import viewsets class UserViewSet(viewsets.ReadOnlyModelViewSet): """ 이 뷰셋은 `list`와 `detail` 기능을 자동으로 지원합니다 """ queryset = User.objects.all() serializer_class = UserSerializer 여기서 사용한 ReadOnlyModelViewSet 클래스는 '읽기 전용' 기능을 자동으로 지원합니다. queryset과 serializer_class 속성은 여전히 설정을 해야 하지만, 두 개의 클래스에 중복으로 설정할 필요는 없어졌습니다. 다음으로는 SnippetList와 SnippetDetail, SnippetHighlight 뷰를 리팩터링해보죠. 이 뷰들을 삭제하고, 아래의 클래스를 입력합니다. from rest_framework.decorators import detail_route class SnippetViewSet(viewsets.ModelViewSet): """ 이 뷰셋은 `list`와 `create`, `retrieve`, `update`, 'destroy` 기능을 자동으로 지원합니다 여기에 `highlight` 기능의 코드만 추가로 작성했습니다 """ queryset = Snippet.objects.all() serializer_class = SnippetSerializer permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsOwnerOrReadOnly,) @detail_route(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 클래스를 사용했습니다. 추가한 highlight 기능에는 여전히 @detail_route 데코레이터를 사용했습니다. 이 데코레이터는 create나 update, delete에 해당하지 않는 기능에 대해 사용하면 됩니다. @detail_route 데코레이터를 사용한 기능은 기본적으로 GET 요청에 응답합니다. methods 인자를 설정하면 POST 요청에도 응답할 수 있습니다. 추가 기능의 URL은 기본적으로 메서드 이름과 같습니다. 이를 변경하고 싶다면 데코레이터에 url_path 인자를 설정하면 됩니다. 뷰셋과 주소를 명시적으로 연결하기 핸들러 메서드는 단지 URL 설정과 연결하는 기능만 담당합니다. 물 밑에서 어떤 일들이 벌어지는지 알아보고자, 여기서는 먼저 뷰셋의 뷰들을 명시적으로 적어보겠습니다. urls.py 파일에서 ViewSet 클래스를 실제 뷰(concrete view)와 연결합니다. from snippets.views import SnippetViewSet, UserViewSet, api_root from rest_framework import renderers snippet_list = SnippetViewSet.as_view({ 'get': 'list', 'post': 'create' }) snippet_detail = SnippetViewSet.as_view({ 'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy' }) snippet_highlight = SnippetViewSet.as_view({ 'get': 'highlight' }, renderer_classes=[renderers.StaticHTMLRenderer]) user_list = UserViewSet.as_view({ 'get': 'list' }) user_detail = UserViewSet.as_view({ 'get': 'retrieve' }) ViewSet 클래스의 뷰들을 HTTP 메서드에 따라 어떻게 실제 뷰와 연결했는지 살펴보세요. 이제 실제 뷰와 URL을 연결해보겠습니다. urlpatterns = format_suffix_patterns([ url(r'^$', api_root), url(r'^snippets/$', snippet_list, name='snippet-list'), url(r'^snippets/(?P<pk>[0-9]+)/$', snippet_detail, name='snippet-detail'), url(r'^snippets/(?P<pk>[0-9]+)/highlight/$', snippet_highlight, name='snippet-highlight'), url(r'^users/$', user_list, name='user-list'), url(r'^users/(?P<pk>[0-9]+)/$', user_detail, name='user-detail') ]) 라우터 사용하기 View 클래스 대신 ViewSet 클래스를 사용했기 때문에, 이제는 URL도 설정할 필요가 없습니다. Router 클래스를 사용하면 뷰 코드와 뷰, URL이 관례적으로 자동 연결됩니다. 단지 뷰를 라우터에 적절히 등록해주기만 하면 됩니다. 그러면 REST 프레임워크가 알아서 다 합니다. urls.py 파일을 다음과 같이 고쳐보죠. from django.conf.urls import url, include from snippets import views from rest_framework.routers import DefaultRouter # 라우터를 생성하고 뷰셋을 등록합니다 router = DefaultRouter() router.register(r'snippets', views.SnippetViewSet) router.register(r'users', views.UserViewSet) # 이제 API URL을 라우터가 자동으로 인식합니다 # 추가로 탐색 가능한 API를 구현하기 위해 로그인에 사용할 URL은 직접 설정을 했습니다 urlpatterns = [ url(r'^', include(router.urls)), url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')) ] 라우터에 뷰셋을 등록하는 일은 url 패턴 설정하기와 비슷합니다. 여기서는 두 개를 등록했는데요. 뷰들에 사용할 URL의 접두어와 뷰셋입니다. DefaultRouter 클래스는 API의 최상단 뷰를 자동으로 생성해주므로, views 모듈에 있는 api_root 메서드와 연결했던 URL도 삭제하였습니다. 뷰? 뷰셋? 장단점 비교하기 뷰셋은 유용한 추상화입니다. API 전반에 걸쳐 일관적인 URL 관례를 구현할 수 있고 작성할 코드 양은 최소한으로 유지할 수 있어서, URL 설정에 낭비될 정성을 API의 상호작용과 표현 자체에 쏟을 수 있습니다. 하지만 이것이 항상 옳다는 뜻은 아닙니다. 클래스 기반 뷰와 함수 기반 뷰에 각각 장단점이 있듯이 말이죠. 뷰셋을 사용하면 명확함이 좀 약해집니다. 회고 정말 적은 양의 코드만으로 pastebin과 같은 웹 API를 구현했습니다. 이 API는 웹 브라우저를 완벽히 지원하고, 인증 기능도 있고, 오브젝트별로 권한도 설정되며 다양한 형태로 렌더링됩니다. 지금까지 기본 Django 뷰에서 시작하여 기능들을 점진적으로 만드는 설계 과정을 차근차근 살펴보았습니다. 최종 코드는 GitHub 에서 볼 수 있고, 라이브 데모 에서 작동 모습을 확인할 수도 있습니다. 더 많은 것들 이제 튜토리얼이 끝났습니다. REST 프레임워크에 대해 더 알고 싶다면 다음 링크들로 시작하면 좋을 겁니다. GitHub 에서 이슈를 등록하거나 리뷰하고, pull requests를 작성해 보세요. REST 프레임워크 사용자 모임 에 가입해서 활동해 보세요. 창시자의 트위터 를 팔로우하고 인사를 나누세요. 이제 멋진 무언가를 만들어 보세요. 번역에 도움을 주신 목돌님과 조청님께 감사합니다. Twitter Facebook Google+ django rest framework 3 DRF3 translate Router ViewSet Django raccoony Software Writer, D9, SMARTSTUDY Seoul, Republic of Korea Twitter Facebook Show Comments Django에서 리턴한 json 파일의 한글이 깨져 보일 때 Django의 HttpResponse를 사용하여 json 형태를 보내주면 한글이 깨지는 경우가 있습니다