본문으로 건너뛰기
김신건의 로그

[DRF] Views: APIView, GenericViews, Mixins, FBV

· 수정 · 📖 약 1분 · 398자/단어 #drf #view #generic-view #apiview #mixin
APIView, @api_view, ListAPIView, RetrieveAPIView, GenericAPIView, DRF mixins

정의

DRF View 4가지 스타일. 자유도 vs 자동화 트레이드오프.

4가지 스타일

flowchart TD
    Q{복잡도}
    Q -->|"완전 자유"| FBV["@api_view (FBV)"]
    Q -->|"OO + 자유"| APIView["APIView"]
    Q -->|"CRUD 반복"| Gen["Generic Views"]
    Q -->|"완전 자동"| VS["ViewSet"]
스타일코드량자유도
@api_view유사 Django FBV최고
APIViewCBV높음
Generic Views몇 줄중간
ViewSet1줄낮음 (custom action 으로 확장)

ViewSet 은 django-drf-viewset 참고.

1. FBV (@api_view)

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status

@api_view(['GET', 'POST'])
def user_list(request):
    if request.method == 'GET':
        users = User.objects.all()
        serializer = UserSerializer(users, many=True)
        return Response(serializer.data)

    elif request.method == 'POST':
        serializer = UserSerializer(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)

Decorator 조합

from rest_framework.decorators import (
    api_view,
    authentication_classes,
    permission_classes,
    throttle_classes,
    renderer_classes,
    parser_classes,
)

@api_view(['GET'])
@authentication_classes([TokenAuthentication])
@permission_classes([IsAuthenticated])
@throttle_classes([UserRateThrottle])
def my_view(request): ...

2. APIView (CBV)

from rest_framework.views import APIView

class UserList(APIView):
    authentication_classes = [SessionAuthentication, TokenAuthentication]
    permission_classes = [IsAuthenticated]
    throttle_classes = [UserRateThrottle]

    def get(self, request):
        users = User.objects.all()
        return Response(UserSerializer(users, many=True).data)

    def post(self, request):
        serializer = UserSerializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status=status.HTTP_201_CREATED)

APIView = Django View + DRF 기능 (인증, 권한, throttle, negotiation).

3. Generic Views

Django CBV 의 DRF 버전. CRUD 자동.

from rest_framework import generics

class UserList(generics.ListCreateAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [IsAuthenticated]

class UserDetail(generics.RetrieveUpdateDestroyAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    permission_classes = [IsAuthenticated]

Generic View 종류

Class메서드의미
ListAPIViewGET목록
CreateAPIViewPOST생성
RetrieveAPIViewGET (id)상세
UpdateAPIViewPUT/PATCH갱신
DestroyAPIViewDELETE삭제
ListCreateAPIViewGET + POST목록 + 생성
RetrieveUpdateAPIViewGET + PUT/PATCH상세 + 갱신
RetrieveDestroyAPIViewGET + DELETE상세 + 삭제
RetrieveUpdateDestroyAPIViewGET + PUT + PATCH + DELETE전체

Mixin 조합

Generic Views 는 Mixin + GenericAPIView 조합:

from rest_framework import mixins, generics

class UserList(
    mixins.ListModelMixin,
    mixins.CreateModelMixin,
    generics.GenericAPIView,
):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.create(request, *args, **kwargs)

Mixin 종류:

Mixin메서드
ListModelMixinlist(request)
CreateModelMixincreate(request)
RetrieveModelMixinretrieve(request)
UpdateModelMixinupdate(request), partial_update(request)
DestroyModelMixindestroy(request)

Override 지점

class ArticleList(generics.ListCreateAPIView):
    serializer_class = ArticleSerializer

    def get_queryset(self):
        """user 별 필터"""
        return Article.objects.filter(author=self.request.user)

    def perform_create(self, serializer):
        """저장 전 커스터마이즈"""
        serializer.save(author=self.request.user)

    def get_serializer_class(self):
        """action 별 다른 serializer"""
        if self.request.method == 'POST':
            return ArticleCreateSerializer
        return ArticleSerializer

    def get_serializer_context(self):
        """context 추가"""
        ctx = super().get_serializer_context()
        ctx['extra'] = 'value'
        return ctx

URL 등록

# urls.py
from django.urls import path

urlpatterns = [
    path('users/', UserList.as_view()),
    path('users/<int:pk>/', UserDetail.as_view()),
]

Class-based view 는 as_view() 필수.

get_object (lookup)

class UserDetail(generics.RetrieveAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer

    lookup_field = 'username'       # 기본 'pk'
    lookup_url_kwarg = 'username'   # URL 의 인자 이름

# urls.py
path('users/<str:username>/', UserDetail.as_view())

Filter + Pagination

Generic Views 는 DEFAULT_PAGINATION_CLASSFILTER_BACKENDS 자동 적용:

class UserList(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    filter_backends = [DjangoFilterBackend, filters.SearchFilter]
    filterset_fields = ['is_staff', 'is_active']
    search_fields = ['username', 'email']
    pagination_class = LimitOffsetPagination

자세한 건 drf-filtering, drf-pagination-throttling.

언제 무엇을?

flowchart TD
    Q{시나리오}
    Q -->|1개 endpoint 특수 로직| FBV["@api_view"]
    Q -->|공유 로직 있는 여러 endpoint| APIView
    Q -->|표준 CRUD, 소량 override| Gen["Generic Views"]
    Q -->|CRUD 완전 자동| VS["ViewSet"]
사용권장
Function 하나 (예: webhook)@api_view
상속으로 공통 로직APIView
표준 CRUDGeneric Views
리소스 완전 자동화ViewSet

다른 프레임워크 비교

FrameworkList/Detail 자동
DRFListAPIView, RetrieveUpdateDestroyAPIView
Spring@RestController + Spring Data REST
RailsScaffold
FastAPI없음 (수동 dependency injection)
NestJSCustom decorator

흔한 함정

WARNING

  1. APIView + as_view() 잊음 = URL 등록 실패.
  2. get_queryset override 안 함 + 큰 queryset = 매번 전체 fetch.
  3. Mixin 순서 잘못 = Mixin 이 GenericAPIView 앞. 순서 중요.
  4. @api_view 없이 함수 = DRF 기능 (permission, throttle) 안 적용.

관련 위키

이 글의 용어 (7개)
[Django] DRF Permission, Throttle, Filterdjango
정의 DRF는 view 호출 전 인증(Authentication) → 권한(Permission) → 스로틀(Throttle) 순으로 검사. 각 단계가 통과해야 view 메서드 실…
[Django] DRF ViewSet, Router, @actiondjango
정의 ViewSet은 같은 리소스의 관련 view들을 클래스 하나로 묶는다. Django의 generic views와 비슷하나 / / / / / action 메서드로 통일. Ro…
[DRF] Filtering: django-filter, SearchFilter, OrderingFilterdjango
정의 Filtering = 쿼리 파라미터로 결과 제한. 3가지 backend + custom. 3가지 내장 Backend 설치 + 설정 1. DjangoFilterBackend …
[DRF] Pagination + Throttlingdjango
정의 Pagination = 큰 목록을 페이지 단위로 나눔. Throttling = 요청 빈도 제한. 둘 다 API 안정성의 기본. Pagination 3종 언제 어느 것을 쓸까…
[DRF] Request + Response 객체django
정의 DRF 의 = Django 의 확장. = 의 확장. 자동 content negotiation + renderer 처리. 요청이 뷰에 도달하기까지 에 값이 실제로 들어가려면 …
[DRF] Routers: DefaultRouter, SimpleRouter, custom actionsdjango
정의 Router = ViewSet 에 대한 URL 자동 생성. Rails 의 와 유사. 왜 Router? 종류 DefaultRouter 생성되는 URL: | URL | Meth…
[DRF] Tutorial + Quickstart: 첫 API 서버 5분django
정의 Django REST Framework (DRF) 를 처음 사용 하는 사람을 위한 순차 시작 가이드. 5분 안에 동작하는 API 서버 완성. DRF 개요는 . Django …

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기