DRF는 RESTful API를 만들기 위한 뷰를 정의하는 CBV 형태의 두 가지 방법이 있다. APIView와 ViewSet이다. 두 가지의 특징과 차이점을 살펴보자
APIView
APIView는 커스텀하기 편한 기본 클래스이다. API View를 사용하면 각 HTTP 메서드(GET, POST, PUT, DELETE 등)를 별도로 정의하고 요청/응답을 수동으로 처리해야 한다. API View를 사용하면 API 로직과 응답 생성을 완벽하게 제어할 수 있지만 더 많은 상용 코드가 필요하다.
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import authentication, permissions
from django.contrib.auth.models import User
class ListUsers(APIView):
"""
View to list all users in the system.
* Requires token authentication.
* Only admin users are able to access this view.
"""
authentication_classes = [authentication.TokenAuthentication]
permission_classes = [permissions.IsAdminUser]
def get(self, request, format=None):
"""
Return a list of all users.
"""
usernames = [user.username for user in User.objects.all()]
return Response(usernames)
ViewSet
ViewSet은 모델에서 CRUD(작성, 읽기, 업데이트, 삭제) 작업을 처리하기 위해 일반적으로 사용되는 일련의 작업을 제공하는 클래스 기반 뷰이다.
from django.contrib.auth.models import User
from django.shortcuts import get_object_or_404
from myapps.serializers import UserSerializer
from rest_framework import viewsets
from rest_framework.response import Response
class UserViewSet(viewsets.ViewSet):
"""
A simple ViewSet for listing or retrieving users.
"""
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)
또한 CRUD에 해당하는 url을 자동으로 생성해준다.
from myapp.views import UserViewSet
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'users', UserViewSet, basename='user')
urlpatterns = router.urls
각 action에 대해 사용권한을 제한할 수 있다.
def get_permissions(self):
"""
Instantiates and returns the list of permissions that this view requires.
"""
if self.action == 'list':
permission_classes = [IsAuthenticated]
else:
permission_classes = [IsAdminUser]
return [permission() for permission in permission_classes]
또한 라우팅을 통해 추가적인 작업을 할 경우 action decorator를 사용하여 해당 메서드를 표현할 수 있다.
from django.contrib.auth.models import User
from rest_framework import status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from myapp.serializers import UserSerializer, PasswordSerializer
class UserViewSet(viewsets.ModelViewSet):
"""
A viewset that provides the standard actions
"""
queryset = User.objects.all()
serializer_class = UserSerializer
@action(detail=True, 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.validated_data['password'])
user.save()
return Response({'status': 'password set'})
else:
return Response(serializer.errors,
status=status.HTTP_400_BAD_REQUEST)
@action(detail=False)
def recent_users(self, request):
recent_users = User.objects.all().order_by('-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)
detail을 True로 설정한 경우 pk를 이용할 수 있으며 url은 다음과 같다.
users/{pk}/set_password/$
'Django' 카테고리의 다른 글
[DRF] Serializer relations (0) | 2023.02.26 |
---|---|
[DRF] create vs perform_create (0) | 2023.02.24 |
Django 구조 잡기 (0) | 2023.02.18 |
[DRF] SearchFilter (0) | 2023.02.16 |
[QuerySet] Q() Objects 알아보기 (0) | 2023.01.18 |