r잡초처럼
바른 프로그래밍
r잡초처럼
전체 방문자
오늘
어제
  • 분류 전체보기 (124)
    • FastAPI (7)
    • 끄적끄적 (2)
    • Python (17)
    • Django (31)
    • Database (2)
    • Docker (7)
    • 디자인패턴 (2)
    • CS 공부 (12)
      • 알고리즘 (2)
      • 자료 구조 (1)
      • 네트워크 (7)
      • IT 지식 (1)
      • 운영체제 (1)
    • 기타 팁들 (10)
    • Aws (2)
    • 독서 (1)
    • 코딩테스트 공부 (1)
      • 백준 (0)
      • 프로그래머스 (1)
    • DevOps (13)
    • TIL (3)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 책 리뷰
  • query param
  • 완벽한 IT 인프라 구축을 위한 Docker
  • 물리 계층
  • 상속 안티 패턴
  • fastapi
  • 랜 카드
  • 컴퓨터 기본 지식
  • 랜과 왠
  • pytest
  • encoding
  • 상속과 컴포지션
  • pycharm
  • 모두의 네트워크
  • 케이블의 종류
  • Batch
  • 파이썬 클린 코드
  • poetry
  • 전기 신호
  • 5장 회사에서 하는 랜 구성
  • validate
  • depends
  • docker
  • preonboarding
  • 네트워크
  • CS 지식
  • cp949
  • 6장
  • 7장
  • dotenv

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
r잡초처럼

바른 프로그래밍

Django

[DRF] APIView vs ViewSet

2023. 2. 20. 20:47

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
    'Django' 카테고리의 다른 글
    • [DRF] Serializer relations
    • [DRF] create vs perform_create
    • Django 구조 잡기
    • [DRF] SearchFilter
    r잡초처럼
    r잡초처럼
    오늘보다 내일 더 나은 개발자가 되기 위한 노력을 기록하는 블로그 입니다.

    티스토리툴바