django-rest-framework 의 APIView 에서 사용하는 def 에 대해 정의

2024. 11. 11. 14:25django/Views

Django REST Framework (DRF)은 Django를 기반으로 한 강력한 웹 API 개발 도구입니다. 그 중 APIView는 DRF에서 가장 기본이 되는 클래스 기반 뷰(Class-Based View)로, HTTP 메서드(GET, POST, PUT, DELETE 등)를 처리하기 위해 def 키워드를 사용하여 메서드를 정의합니다. 이 답변에서는 APIView에서 사용하는 def 메서드의 정의와 예제를 상세히 설명하겠습니다.

APIView란?

APIView는 DRF에서 제공하는 클래스 기반 뷰로, Django의 기본 View 클래스를 확장하여 RESTful API를 쉽게 구축할 수 있도록 도와줍니다. APIView는 요청(Request)과 응답(Response)을 처리하며, 다양한 HTTP 메서드를 지원합니다.

def 메서드 정의하기

APIView를 사용할 때, HTTP 메서드에 대응하는 메서드를 def 키워드를 사용하여 클래스 내에 정의합니다. 주요 메서드는 다음과 같습니다:

  • get: GET 요청을 처리합니다.
  • post: POST 요청을 처리합니다.
  • put: PUT 요청을 처리합니다.
  • patch: PATCH 요청을 처리합니다.
  • delete: DELETE 요청을 처리합니다.

각 메서드는 요청을 받아 적절한 응답을 반환하는 역할을 합니다.

주요 메서드 정의 및 예제

1. get 메서드

get 메서드는 클라이언트가 데이터를 조회할 때 사용됩니다. 예를 들어, 특정 객체의 세부 정보를 가져오거나, 객체 목록을 반환할 때 사용됩니다.

예제: 단일 객체 조회

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Book
from .serializers import BookSerializer

class BookDetail(APIView):
    def get(self, request, pk, format=None):
        try:
            book = Book.objects.get(pk=pk)
        except Book.DoesNotExist:
            return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)

        serializer = BookSerializer(book)
        return Response(serializer.data, status=status.HTTP_200_OK)

설명:

  • get 메서드는 특정 Book 객체를 조회합니다.
  • pk(Primary Key)를 통해 객체를 찾고, 존재하지 않으면 404 오류를 반환합니다.
  • 존재하면 직렬화(serializer)를 통해 데이터를 JSON 형식으로 응답합니다.

2. post 메서드

post 메서드는 클라이언트가 새로운 데이터를 생성할 때 사용됩니다. 예를 들어, 새로운 객체를 데이터베이스에 추가할 때 사용됩니다.

예제: 새 객체 생성

class BookList(APIView):
    def post(self, request, format=None):
        serializer = BookSerializer(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)

설명:

  • post 메서드는 클라이언트로부터 받은 데이터를 직렬화하고, 유효성을 검사합니다.
  • 유효하면 객체를 저장하고, 201 Created 상태와 함께 저장된 데이터를 반환합니다.
  • 유효하지 않으면 400 Bad Request 상태와 함께 오류를 반환합니다.

3. put 메서드

put 메서드는 클라이언트가 기존 데이터를 전체적으로 업데이트할 때 사용됩니다. 기존 객체를 완전히 교체합니다.

예제: 객체 전체 업데이트

class BookDetail(APIView):
    def put(self, request, pk, format=None):
        try:
            book = Book.objects.get(pk=pk)
        except Book.DoesNotExist:
            return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)

        serializer = BookSerializer(book, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

설명:

  • put 메서드는 특정 Book 객체를 찾아 클라이언트로부터 받은 데이터로 업데이트합니다.
  • 유효성 검사 후 저장하고, 성공 시 업데이트된 데이터를 반환합니다.
  • 객체가 존재하지 않으면 404 오류를, 데이터가 유효하지 않으면 400 오류를 반환합니다.

4. patch 메서드

patch 메서드는 클라이언트가 기존 데이터의 일부만 업데이트할 때 사용됩니다. 부분적인 수정이 가능합니다.

예제: 객체 부분 업데이트

class BookDetail(APIView):
    def patch(self, request, pk, format=None):
        try:
            book = Book.objects.get(pk=pk)
        except Book.DoesNotExist:
            return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)

        serializer = BookSerializer(book, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

설명:

  • patch 메서드는 특정 Book 객체를 찾아 클라이언트로부터 받은 일부 데이터로 업데이트합니다.
  • partial=True를 설정하여 부분 업데이트를 허용합니다.
  • 유효성 검사 후 저장하고, 성공 시 업데이트된 데이터를 반환합니다.
  • 객체가 존재하지 않으면 404 오류를, 데이터가 유효하지 않으면 400 오류를 반환합니다.

5. delete 메서드

delete 메서드는 클라이언트가 특정 데이터를 삭제할 때 사용됩니다.

예제: 객체 삭제

class BookDetail(APIView):
    def delete(self, request, pk, format=None):
        try:
            book = Book.objects.get(pk=pk)
        except Book.DoesNotExist:
            return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)

        book.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

설명:

  • delete 메서드는 특정 Book 객체를 찾아 삭제합니다.
  • 삭제가 성공하면 204 No Content 상태를 반환합니다.
  • 객체가 존재하지 않으면 404 오류를 반환합니다.

전체 예제: APIView를 이용한 CRUD API

아래는 Book 모델을 대상으로 한 전체 CRUD(Create, Read, Update, Delete) API 예제입니다.

모델 (models.py):

from django.db import models

class Book(models.Model):
    title = models.CharField(max_length=100)
    author = models.CharField(max_length=100)
    published_date = models.DateField()

    def __str__(self):
        return self.title

직렬화기 (serializers.py):

from rest_framework import serializers
from .models import Book

class BookSerializer(serializers.ModelSerializer):
    class Meta:
        model = Book
        fields = '__all__'

뷰 (views.py):

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from .models import Book
from .serializers import BookSerializer

class BookList(APIView):
    """
    책 목록 조회 및 새로운 책 생성
    """
    def get(self, request, format=None):
        books = Book.objects.all()
        serializer = BookSerializer(books, many=True)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def post(self, request, format=None):
        serializer = BookSerializer(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)

class BookDetail(APIView):
    """
    특정 책 조회, 업데이트, 삭제
    """
    def get_object(self, pk):
        try:
            return Book.objects.get(pk=pk)
        except Book.DoesNotExist:
            return None

    def get(self, request, pk, format=None):
        book = self.get_object(pk)
        if not book:
            return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)

        serializer = BookSerializer(book)
        return Response(serializer.data, status=status.HTTP_200_OK)

    def put(self, request, pk, format=None):
        book = self.get_object(pk)
        if not book:
            return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)

        serializer = BookSerializer(book, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def patch(self, request, pk, format=None):
        book = self.get_object(pk)
        if not book:
            return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)

        serializer = BookSerializer(book, data=request.data, partial=True)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_200_OK)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, pk, format=None):
        book = self.get_object(pk)
        if not book:
            return Response({'error': 'Book not found'}, status=status.HTTP_404_NOT_FOUND)

        book.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

설명:

  • BookList 클래스:

    • get: 모든 책의 목록을 조회하여 반환합니다.
    • post: 새로운 책을 생성합니다.
  • BookDetail 클래스:

    • get: 특정 pk(Primary Key)를 가진 책을 조회하여 반환합니다.
    • put: 특정 책을 전체적으로 업데이트합니다.
    • patch: 특정 책을 부분적으로 업데이트합니다.
    • delete: 특정 책을 삭제합니다.

URL 설정 (urls.py):

from django.urls import path
from .views import BookList, BookDetail

urlpatterns = [
    path('books/', BookList.as_view(), name='book-list'),
    path('books/<int:pk>/', BookDetail.as_view(), name='book-detail'),
]

설명:

  • /books/: 책 목록 조회 및 새 책 생성.
  • /books/<pk>/: 특정 책 조회, 업데이트, 삭제.

추가 팁

  1. 권한 및 인증 설정:
    APIView는 권한 및 인증을 쉽게 설정할 수 있습니다. 예를 들어, 인증된 사용자만 접근하도록 설정할 수 있습니다.

    from rest_framework.permissions import IsAuthenticated
    
    class BookList(APIView):
        permission_classes = [IsAuthenticated]
    
        def get(self, request, format=None):
            # ...
  2. 예외 처리:
    get_object 메서드를 활용하여 객체를 가져오고, 존재하지 않을 경우 적절히 처리하는 것이 좋습니다.

  3. 응답 상태 코드:
    HTTP 상태 코드를 적절히 설정하여 클라이언트에게 정확한 정보를 전달합니다. 예를 들어, 성공 시 200 OK, 생성 시 201 Created, 삭제 시 204 No Content 등을 사용합니다.

  4. Serializer 유효성 검사:
    데이터를 저장하거나 업데이트하기 전에 반드시 유효성을 검사하여 데이터의 무결성을 유지합니다.

요약

  • APIView는 DRF에서 HTTP 메서드를 처리하기 위해 def 키워드를 사용하여 메서드를 정의하는 클래스 기반 뷰입니다.
  • 주요 메서드로는 get, post, put, patch, delete가 있으며, 각 메서드는 해당 HTTP 요청을 처리합니다.
  • APIView를 사용하면 RESTful API의 CRUD(Create, Read, Update, Delete) 작업을 쉽게 구현할 수 있습니다.
  • 직렬화기(Serializer)를 활용하여 데이터의 직렬화 및 역직렬화를 관리합니다.
  • 권한 및 인증, 예외 처리, 상태 코드 관리 등 다양한 기능을 통해 견고한 API를 구축할 수 있습니다.

APIView는 유연성과 강력한 기능을 제공하지만, 경우에 따라 DRF에서 제공하는 제네릭 뷰(Generic Views)뷰셋(ViewSets)을 사용하는 것이 더 간편할 수 있습니다. 프로젝트의 요구사항에 따라 적절한 뷰를 선택하여 사용