시작
이번 포스트에서는 DRF(Django Rest Framework) 튜토리얼을 통해 ViewSets와 Routers를 사용하는 방법에 대해 알아보겠습니다. 본 포스트는 macOS와 VS Code 환경에서 진행됩니다.
본문
ViewSets으로 리팩토링
UserList
와 UserDetail
을 하나의 UserViewSet
클래스로 리팩터링 합니다.
from rest_framework import viewsets
class UserViewSet(viewsets.ReadOnlyModelViewSet):
"""
이 뷰셋은 `list` 및 `retrieve` 액션을 자동으로 제공합니다.
"""
queryset = User.objects.all()
serializer_class = UserSerializer
ReadOnlyModelViewSet
을 사용하여 기본적인 읽기 전용
작업을 자동으로 제공합니다. 이렇게 하면 두 개의 별도 클래스를 사용하는 대신 queryset
과 serializer_class
만 설정하면 됩니다.
다음으로 SnippetList
, SnippetDetail
, SnippetHighlight
뷰 클래스를 SnippetViewSet
으로 교체합니다.
from rest_framework import permissions
from rest_framework import renderers
from rest_framework.decorators import action
from rest_framework.response import Response
class SnippetViewSet(viewsets.ModelViewSet):
"""
이 뷰셋은 `list`, `create`, `retrieve`, `update`, `destroy` 기능을 자동으로 제공합니다.
추가적으로 `highlight` 기능을 제공합니다.
"""
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
을 사용하면 기본적인 읽기 및 쓰기 작업을 모두 처리할 수 있습니다.
여기서 @action
데코레이터를 사용하여 highlight
기능을 추가하였고 이 데코레이터는 사용자 정의 엔드포인트를 추가하는 데 유용합니다.
기본적으로 GET
메서드를 사용하며 methods
키워드를 사용하여 커스텀 메서드를 변경할 수 있습니다.
class MyViewSet(viewsets.ModelViewSet):
@action(detail=True, methods=['post'])
def custom_action(self, request, *args, **kwargs):
pass
기본적으로 사용자 정의 작업의 URL은 메서드 이름에 따라 설정됩니다. url_path
키워드를 사용하면 URL 경로를 변경할 수 있습니다.
class MyViewSet(viewsets.ModelViewSet):
@action(detail=True, methods=['post'], url_path='custom-path')
def custom_action(self, request, *args, **kwargs):
pass
ViewSet을 URL에 명시적으로 바인딩
snippets/urls.py
파일에서 ViewSet
클래스를 URL에 바인딩합니다.
from rest_framework import renderers
from snippets.views import api_root, SnippetViewSet, UserViewSet
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'
})
각 뷰에 필요한 작업에 HTTP 메서드를 바인딩하여 각 ViewSet 클래스에서 여러 뷰를 생성할 수 있습니다.
이제 바인딩한 뷰를 URL conf에 등록합니다.
urlpatterns = format_suffix_patterns([
path('', api_root),
path('snippets/', snippet_list, name='snippet-list'),
path('snippets/<int:pk>/', snippet_detail, name='snippet-detail'),
path('snippets/<int:pk>/highlight/', snippet_highlight, name='snippet-highlight'),
path('users/', user_list, name='user-list'),
path('users/<int:pk>/', user_detail, name='user-detail')
])
Routers 사용
Router
클래스를 사용하면 URL conf를 자동으로 설정할 수 있습니다.
from django.urls import path, include
from rest_framework.routers import DefaultRouter
from snippets import views
# 라우터를 생성하고 ViewSet을 등록합니다.
router = DefaultRouter()
router.register(r'snippets', views.SnippetViewSet, basename='snippet')
router.register(r'users', views.UserViewSet, basename='user')
# API URL은 라우터에 의해 자동으로 결정됩니다.
urlpatterns = [
path('', include(router.urls)),
]
DefaultRouter
클래스는 API 루트 보기도 자동으로 생성하므로 api_root
함수는 더 이상 필요 없습니다.
마무리
이번 포스트에서는 DRF의 ViewSets와 Routers를 사용하여 코드의 간결함과 추상화를 어떻게 얻을 수 있는지 살펴보았습니다. ViewSets는 코드를 간결하게 유지하면서도 URL 규칙을 일관되게 관리할 수 있는 강력한 도구입니다. ViewSets를 사용하면 코드가 더 간결해지고 URL 규칙이 일관되게 유지됩니다. URL 구성의 세부 사항보다 API의 상호작용과 표현에 집중할 수 있습니다. 그러나 ViewSets는 API 뷰를 개별적으로 구축하는 것보다 덜 명시적일 수 있습니다.
참고자료
'Django' 카테고리의 다른 글
STATICFILES_DIR vs STATIC_ROOT (0) | 2024.10.21 |
---|---|
DRF Tutorial 5 Relationships & Hyperlinked APIs (0) | 2024.09.14 |
DRF Tutorial 4 Authentication & Permissions (1) | 2024.09.14 |
DRF Tutorial 3 Class-based Views (0) | 2024.09.14 |
DRF Tutorial 2 Requests and Responses (0) | 2024.09.11 |
댓글