728x90
반응형
Function-Based Views vs Class-Based Views
Function-Based Views (FBV) :
- 뷰를 단순한 함수로 정의
- 간단한 작업을 처리하기에 적합하며, 코드가 짧고 직관적
from rest_framework.decorators import api_view
from rest_framework.response import Response
@api_view(['GET'])
def hello_world(request):
return Response({'message': 'Hello, World!'})
Class-Based Views (CBV) :
- 뷰를 클래스로 정의하며, DRF 의 APIView 나 Generic Views 등을 상속받아 사용
- 복잡한 작업을 처리하거나 재사용성을 높이고자 할 때 적합
from rest_framework.views import APIView
from rest_framework.response import Response
class HelloWorldAPIView(APIView):
def get(self, request):
return Response({'message': 'Hello, World!'})
FBV 는 규모가 작고 간단한 API 엔드포인트를 빠르게 구현할 때 적합하며 CBV 는 규모가 크고 복잡한 API 엔드포인트를 구현할 때, 재사용성과 확장성이 중요할 때, 그리고 DRF의 기능 (ViewSet, Generic Views 등) 을 최대한 활용하고 싶을 때 적합합니다. 이러한 이유로 DRF 에서는 CBV 를 사용하는 것이 더 일반적입니다.
APIView vs Generic View vs ModelViewSet
APIView: 기본 제공 기능 없이 모든 것을 직접 구현
- 특징: 최소한의 추상화를 제공. 모든 HTTP 메서드 (get, post, put, delete 등) 를 직접 구현해야 함
- 장점: 높은 커스터마이징 가능성
- 단점: 기본 CRUD 기능도 직접 구현해야 하므로 코드량이 많아질 수 있음
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Item
from .serializers import ItemSerializer
class ItemAPIView(APIView):
def get(self, request):
items = Item.objects.all()
serializer = ItemSerializer(items, many=True)
return Response(serializer.data)
def post(self, request):
serializer = ItemSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Generic View: 기본 CRUD 작업 중 일부를 제공
- 특징: RESTful 작업 중 일부를 미리 구현한 클래스
- 장점: 반복 작업을 줄이고 CRUD 기능을 빠르게 생성 가능
- 단점: 특정 HTTP 메서드 (예: delete 등) 를 추가로 구현하려면 커스터마이징 필요
from rest_framework.generics import ListCreateAPIView
from .models import Item
from .serializers import ItemSerializer
class ItemListCreateView(ListCreateAPIView):
queryset = Item.objects.all()
serializer_class = ItemSerializer
- queryset, serializer_class 를 지정하는 것만으로 기본 CRUD 기능을 자동으로 제공
- 주요 Generic Views:
- ListCreateAPIView
- GET: 객체 목록 조회
- POST: 객체 생성
- RetrieveUpdateDestroyAPIView
- GET: 단일 객체 조회
- PUT / PATCH: 객체 수정
- DELETE: 객체 삭제
- ListAPIView
- GET: 객체 목록 조회
- CreateAPIView
- POST: 객체 생성
- RetrieveAPIView
- GET: 단일 객체 조회
- UpdateAPIView
- PUT / PATCH: 객체 수정
- DestroyAPIView
- DELETE: 객체 삭제
- ListCreateAPIView
ModelViewSet: CRUD 전체를 미리 구현하고 URL 라우팅까지 자동화
- 특징: CRUD 작업을 모두 포함하며, URL 라우팅까지 자동화
- 장점: 가장 간단하게 CRUD 기능을 제공하며, 코드량을 크게 줄임
- 단점: 지나치게 추상화되어 있어 세부 커스터마이징이 필요할 때는 오히려 불편
# app_name/views.py
from rest_framework.viewsets import ModelViewSet
from .models import BlogPost
from .serializers import BlogPostSerializer
class BlogPostViewSet(ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogPostSerializer
- queryset, serializer_class 를 지정하는 것만으로 기본 CRUD 기능을 자동으로 제공
# app_name/urls.py
from rest_framework.routers import DefaultRouter
from .views import BlogPostViewSet
router = DefaultRouter()
router.register(r'blogposts', BlogPostViewSet, basename='blogpost')
urlpatterns = router.urls
- 위처럼 작성하면, 아래와 같은 CRUD URL이 자동 생성:
- GET (목록 조회) : /blogposts/
- POST (새 객체 생성) : /blogposts/
- GET (특정 객체 조회) : /blogposts/<pk>/
- PUT (특정 객체 수정) : /blogposts/<pk>/
- PATCH (특정 객체 부분 수정) : /blogposts/<pk>/
- DELETE (특정 객체 삭제) : /blogposts/<pk>/
Generic View vs ModelViewSet 구현
특징 | Generic View | ModelViewSet |
URL 정의 방식 | 직접 각각의 경로 정의 | Router 를 사용해 URL 라우팅 자동 생성 |
URL 커스터마이징 | 세밀하게 커스터마이징 가능 | 기본 CRUD 패턴 자동화, 세밀한 라우팅은 추가 작업 필요 |
코드량 | 더 많은 코드 작성 필요 | 라우팅 자동화로 코드량 적음 |
로직 추가 및 커스터마이징 | 새로운 뷰 클래스를 생성하거나 기존 클래스를 확장 | 메서드 오버라이드 또는 @action 사용 |
적합한 상황 | 복잡한 URL 구조, 특정 HTTP 메서드별 상세 로직 필요 시 | 단순 CRUD 중심의 API 구현 시 |
Generic View
# app_name/views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, generics
class BlogPostHighlightView(APIView):
def post(self, request, pk, *args, **kwargs):
try:
post = BlogPost.objects.get(pk=pk)
post.is_highlighted = True
post.save()
return Response({'message': 'Post highlighted successfully'}, status=status.HTTP_200_OK)
except BlogPost.DoesNotExist:
return Response({'error': 'Post not found'}, status=status.HTTP_404_NOT_FOUND)
class BlogPostListCreateView(generics.ListCreateAPIView):
queryset = BlogPost.objects.all()
serializer_class = BlogPostSerializer
# app_name/urls.py
from django.urls import path
from .views import BlogPostListCreateView, BlogPostHighlightView
urlpatterns = [
path('posts/', BlogPostListCreateView.as_view(), name='blogpost-list-create'),
path('posts/<int:pk>/highlight/', BlogPostHighlightView.as_view(), name='blogpost-highlight'),
]
ModelViewSet
# app_name/views.py
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework import status, viewsets
class BlogPostViewSet(viewsets.ModelViewSet):
queryset = BlogPost.objects.all()
serializer_class = BlogPostSerializer
@action(detail=True, methods=['post'])
def highlight(self, request, pk=None):
post = self.get_object()
post.is_highlighted = True
post.save()
return Response({'message': 'Post highlighted successfully'}, status=status.HTTP_200_OK)
# app_name/urls.py
from rest_framework.routers import DefaultRouter
from .views import BlogPostViewSet
router = DefaultRouter()
router.register(r'posts', BlogPostViewSet, basename='blogpost')
urlpatterns = router.urls
728x90
반응형
'Dev > Web Programming' 카테고리의 다른 글
Django REST Framework 입문 가이드 (5) | 2024.11.18 |
---|---|
Django vs Django REST Framework (4) | 2024.11.12 |
Django 입문 가이드 (7) | 2024.11.05 |
React 와 Django 간의 데이터 통신: HTTP 와 REST API 로 구현하기 (5) | 2024.10.14 |