ViewSet
Django REST framework๋ ViewSet
์ด๋ผ๋ ๋จ์ผ ํด๋์ค์์ ๊ด๋ จ๋ ๋
ผ๋ฆฌ๋ฅผ ๊ฒฐํฉํ ์ ์๋ค. ViewSet
์ ๋จ์ํ get()
์ด๋ post()
์ ๊ฐ์ ๋ฉ์๋ ํธ๋ค๋ฌ๋ฅผ ์ ๊ณตํ์ง ์์ผ๋ฉฐ, ๋์ list()
์ create()
๊ฐ์ ์ก์
์ ์ ๊ณตํ๋ค(CBV ์ ํ). ViewSet
์ method ํธ๋ค๋ฌ๋ as_view()
ํจ์๊ฐ ํธ์ถ๋์ด view๊ฐ ๋๋๋ ์์ ์ ํด๋น ์ก์
์๋ง ๋ฐ์ธ๋ฉ๋๋ค.
๋ฐ์ธ๋ฉ(binding)
๊ฐ์ข ๊ฐ๋ค์ด ํ์ ๋์ด ๋ ์ด์ ๋ณ๊ฒฝํ ์ ์๋ ์ํ๊ฐ ๋๋ ๊ฒ์ด๋ค. ์๋ณ์(identifier)๊ฐ ๊ทธ ๋์์ธ ๋ฉ๋ชจ๋ฆฌ ์ฃผ์, ๋ฐ์ดํฐํ ๋๋ ์ค์ ๊ฐ์ผ๋ก ๋ฐฐ์ ๋๋ ๊ฒ์ ๋ปํ๋ค.
์ผ๋ฐ์ ์ผ๋ก url์ค์ ์์ view๋ฅผ ๋ช
์์ ์ผ๋ก ๋ฑ๋กํ๋ ๋์ router
ํด๋์ค๋ก ๋ฑ๋กํ์ฌ ์๋์ผ๋ก url์ ์ค์ ํ๋ค.
START VIEWSETS
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from .serializers import UserSerializer
from rest_framework import viewsets
from rest_framework.response import Response
class UserViewSet(viewsets.ViewSet):
def list(self, request):
queryset = User.objects.all()
serializer = UserSerializer(queryset, many=True)
return Response(serializer.data)
def retrieve(self, request, pk=None):
queryset = User.objects.all()
user = get_object_or_404(queryset, pk=pk)
serializer = UserSerializer(user)
return Response(serializer.data)
ํ์์์๋ ์ด ViewSet์ ์๋์ ๊ฐ์ด ๊ฐ๋ณ ๋ทฐ ๋ฐ์ธ๋ฉ์ ํ ์ ์๋ค.
user_list = UserViewSet.as_view({'get': 'list'})
user_detail = UserViewSet.as_view({'get': 'retrieve'})
์ผ๋ฐ์ ์ผ๋ก ๊ฐ๋ณ ๋ทฐ ๋ฐ์ธ๋ฉ์ ํ์ง ์์ผ๋ฉฐ, ViewSet์ ๋ผ์ฐํฐ์ ๋ฑ๋กํ์ฌ ์๋์ผ๋ก URLconf(url ์ค์ ํ์ผ)์ด ์์ฑ๋๋๋ก ํ๋ค.
from .views import UserViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'users', UserViewSet)
urlpatterns - router.urls
์ด๋ viewset์ ๋ณธ์ธ์ด ์์ฑํ๋ ๊ฒ๋ณด๋ค ๊ธฐ๋ณธ ๋์์ ์ ๊ณตํด์ฃผ๋ ๊ธฐ๋ณธ ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๊ถ์ฅํ๋ค.
class UserViewSet(viewsets.ModelViewSet):
serializer_class = UserSerializer
queryset = User.objects.all()
์ฅ์
view ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๋ณด๋ค viewsets ํด๋์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์ข์ ์ ์ด 2๊ฐ์ง ์๋ค.
๋ฐ๋ณต๋๋ ๋ก์ง์ ํ๋์ ํด๋์ค๋ก ๊ฒฐํฉํ ์ ์๋ค. ์ฆ, viewsets์ ์ด์ฉํ๋ฉด queryset์ ๋จ ํ๋ฒ๋ง ์ ์ํ๋ฉด ๋๋ค.
router๋ฅผ ์ฌ์ฉํจ์ผ๋ก์จ, URLconf(url ์ค์ ํ์ผ)์ ๋ค๋ฃฐ ํ์๊ฐ ์์ด์ง๋ค.
ํ์ง๋ง ์๋์ ๊ฐ์ trade-off๋ ์๋ค.
view์ url์ค์ ์ ์ฌ์ฉํ๋ฉด ๋ณด๋ค ๋ช ํํ๊ณ ์์ธํ๊ฒ ์ ์ดํ ์ ์๋ค.
ViewSet
์ ๋น ๋ฅด๊ฒ ์คํํ๊ฑฐ๋ ๋๊ท๋ชจ API๊ฐ ์๋ ๊ฒฝ์ฐ, ๋๋ ์ ์ฒด์ ์ผ๋ก ์ผ๊ด๋ URLconf๋ฅผ ์ ์ฉํ๋ ค๋ ๊ฒฝ์ฐ์ ์ ๋ฆฌํ๋ค.
MARKING EXTRA ACTIONS FOR ROUTING
REST framework์ ํฌํจ๋ ๊ธฐ๋ณธ router๋ create / retrieve / update / destroy ์คํ์ผ ์์ ์ ๊ธฐ๋ณธ method๋ฅผ ์ ๊ณตํ๋ค.
class UserViewSet(viewsets.ViewSet):
"""
Example empty viewset demonstrating the standard
actions that will be handled by a router class.
If you're using format suffixes, make sure to also include
the 'format=None' keyword argument for each action.
"""
def list(self, request):
pass
def create(self, request):
pass
def retrieve(self, request, pk=None):
pass
def update(self, request, pk=None):
pass
def partial_update(self, request, pk=None):
pass
def destroy(self, request, pk=None):
pass
๋ผ์ฐํ
์ด ํ์ํ ์์ ๋ฉ์๋๊ฐ ์๋ ๊ฒฝ์ฐ์๋ @detail_router
๋๋ @list_router
๋ฐ์ฝ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ์ฌ ๋ผ์ฐํ
์ ํ์๋ก ํ๋ค๋ ๊ฒ์ ํ์ํ ์ ์๋ค.
@detail_router
๋ URL ํจํด์ pk๋ฅผ ํฌํจํ๋ฉฐ ๋จ์ผ ์ธ์คํด์ค๋ฅผ ์๊ตฌํ๋ ๋ฉ์๋์ ๋ํ ๊ฒ์ด๋ค.@list_router
๋ ๊ฐ์ฒด ๋ชฉ๋ก์์ ์๋ํ๋ ๋ฉ์๋์ ๋ํ ๊ฒ์ด๋ค.
rom django.contrib.auth.models import User
from rest_framework import status
from rest_framework import viewsets
from rest_framework.decorators import detail_route, list_route
from rest_framework.response import Response
from .serializers import UserSerializer, PasswordSerializer
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
@detail_route(methods=['post'])
def set_password(self, request, pk=None):
user = self.get_object()
serializer = PasswordSerializer(data=request.data)
if serializer.is_valid():
user.set_password(serializer.data['password'])
user.save()
return Response({'status': 'password set'})
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
@list_route()
def recent_users(self, request):
recent_users = User.objects.all().order('-last_login')
page = self.paginate_queryset(recent_users)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(recent_users, many=True)
return Response(serializer.data)
๋ฐ์ฝ๋ ์ดํฐ๋ ์ค์ง ๋ผ์ฐํ ๋ View์์๋ง ์ถ๊ฐ์ ์ธ arguments๋ฅผ ๋ฐ์ ์ ์๋ค.
@detail_route(methods=['post'], permission_classes=[IsAdminOrIsSelf])
def set_password(self, request, pk=None):
...
ํด๋น ๋ฐ์ฝ๋ ์ดํฐ๋ ๊ธฐ๋ณธ์ ์ผ๋ก GET
request๋ฅผ routingํ์ง๋ง methods
์ธ์๋ฅผ ์ฌ์ฉํ์ฌ ๋ค๋ฅธ HTTP Method๋ก routingํ ์ ์๋ค.
@detail_route(methods=['post', 'delete'])
def unset_password(self, request, pk=None):
...
์์ ๋๊ฐ์ง ์๋ก์ด action๋ค์ ^users/{pk}/set_password/$
, ^users/{pk}/unset_password/$
๋ก ์ฌ์ฉํ ์ ์๋ค.
API REFERENCE
ViewSet
ViewSet
ํด๋์ค๋ APIView
์์ ์์๋ฐ๋๋ค. permission_classes
, authentication_classes
์ ๊ฐ์ ํ์ค ์์ฑ์ ์ด์ฉํ์ฌ API ์ ์ฑ
์ ํต์ ํ ์ ์๋ค.
ViewSet
ํด๋์ค๋ action์ ๊ตฌํ์ ์ ๊ณตํ์ง ์๋๋ค. ViewSet
ํด๋์ค๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ํด๋น ํด๋์ค๋ฅผ overriceํ๊ณ , ๋ช
์์ ์ผ๋ก action์ ์ ์ํด์ผํ๋ค.
GenericViewSet
GenericViewSet
ํด๋์ค๋ GenericAPIView
์์ ์์ ๋ฐ๋๋ค. get_object
, get_queryset
๋ฉ์๋์ ๋ค๋ฅธ generic view์ ๊ธฐ๋ณธ action์ ์ ๊ณตํ์ง๋ง, ๊ธฐ๋ณธ์ ์ผ๋ก๋ ์ด๋ ํ ์ก์
๋ ํฌํจํ๊ณ ์์ง ์๋ค.
GenericViewSet
ํด๋์ค๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ํด๋น ํด๋์ค๋ฅผ overrideํ๊ณ ํ์ํ mixin
ํด๋์ค๋ฅผ ํผํฉํ์ฌ ๋ช
์์ ์ผ๋ก action์ ์ ์ํด์ํ๋ค.
ModelViewSet
ModelViewSet
ํด๋์ค๋ GenericAPIView
๋ฅผ ์์ํ๊ณ ๋ค์์ mixin
ํด๋์ค์ ๋์์ ํผํฉํ์ฌ ๋ค์ํ action์ ๋ํ ๊ตฌํ์ ํฌํจํ๋ค.
.list()
, .retrieve()
, .create()
, .update()
, .partial_update()
, .destroy()
๋ฅผ ์ ๊ณตํ๋ค.
class AccountViewSet(viewsets.ModelViewSet):
queryset = Account.objects.all()
serializer_class = AccountSerializer
permission_classes = [IsAccountAdminOrReadOnly]
GenericAPIView
๋ฅผ ์์๋ฐ๊ณ ์๊ธฐ ๋๋ฌธ์ ๊ธฐ๋ณธ์ ์ผ๋ก queryset
๊ณผ serializer_class
์์ฑ์ ํ์๋ก ์ ๊ณตํด์ผํ๋ค.
class AccountViewSet(viewsets.ModelViewSet):
serializer_class = AccountSerializer
permission_classes = [IsAccountAdminOrReadOnly]
def get_queryset(self):
return self.request.user.accounts.all()
queryset์ ๋์ ์ผ๋ก ๊ฒฐ์ ํ๋ viewsets์ ์ฌ์ฉํ๋ ค๋ฉด ์์ ๊ฐ์ด ๋ฉ์๋ ์ค๋ฒ๋ผ์ด๋๋ฅผ ํ ์ ์๋ค.
์ฌ๊ธฐ์ ์ฃผ์ํด์ผํ ์ ์ด ์๋ค. ViewSet
์ queryset
์์ฑ์ ์ ๊ฑฐํ๋ฉด ์ฐ๊ฒฐ๋ ๋ผ์ฐํฐ๊ฐ ๋ชจ๋ธ์ base_name์ ์๋์ผ๋ก ํ์์ํฌ ์ ์์ผ๋ฏ๋ก base_name์ kwarg๋ฅผ ์ง์ ํด์ผํ๋ค. ์ด ํด๋์ค๋ ๊ธฐ๋ณธ์ ์ผ๋ก create / list / retrieve / update /destroy ์ก์
์ ์ ๊ณตํ์ง๋ง ํ์ค ๊ถํ ํด๋์ค(permission)๋ฅผ ์ฌ์ฉํด ์ ํํ ์ ์๋ค.
ReadOnlyModelViewSet
ReadOnlyModelViewSet
ํด๋์ค๋ GenericAPIView
๋ฅผ ์์ํ๋ค. ModelViewSet
๊ณผ ๋์ผํ๊ฒ ๋ค์ํ action์ ๋ํ ๊ตฌํ๋ ํฌํจ๋์ง๋ง ์ค์ง ์ฝ๊ธฐ ์ ์ฉ action์ธ .list()
์ .retrieve()
๋ง ์ ๊ณตํ๋ค.
class AccountViewSet(viewsets.ReadOnlyModelViewSet):
queryset = Account.objects.all()
serializer_class = AccountSerializer
์ฐธ๊ณ ๋งํฌ
Last updated
Was this helpful?