DRF Tutorial

DRF Tutorial 2: Requests and Responses 1

waterclean101 2023. 2. 14. 14:04

이제부터 REST 프레임워크의 핵심을 본격적으로 다루기 시작하겠다. 몇 가지 필수 구성 요소를 소개한다.

 

Request objects

REST 프레임워크는 일반 HttpRequest를 확장하고 보다 유연한 요청 구문 분석을 제공하는 Request 객체를 도입했다. Request objects의 핵심 기능은 request.data 속성으로, request.POST와 유사하지만 웹 API 작업에 더 유용하다.

request.POST  # Only handles form data.  Only works for 'POST' method.
request.data  # Handles arbitrary data.  Works for 'POST', 'PUT' and 'PATCH' methods.

 

Response objects

REST 프레임워크는 렌더링되지 않은 콘텐츠를 가져와 클라이언트에 반환할 올바른 콘텐츠 유형을 결정하는 콘텐츠 협상에 사용하는 TemplateResponse의 한 유형인 응답 객체를 도입했다.

return Response(data)  # Renders to content type as requested by the client.

 

Status codes

뷰에서 숫자 HTTP 상태 코드를 사용한다해도 항상 명확하게 상태를 알 수 있는 것은 아니며, 오류 코드가 잘못되어도 알아차리지 못하기 쉽다. REST framework는 각 상태 코드에 대해 상태 모듈의 HTTP_400_BAD_REQUEST와 같은 보다 명시적인 식별자를 제공한다. 숫자 식별자를 사용하는 것보다 REST framework의 식별자를 사용하는 것이 좋다.

 

Wrapping API views

REST framework는 API 뷰를 작성하는 데 사용할 수 있는 두 가지 wrapper를 제공한다.

  1. 함수 기반 뷰로 작업하기 위한 @api_view 데코레이터
  2. 클래스 기반 뷰로 작업하기 위한 APIView 클래스.

이러한 wrapper는 뷰에서 요청 인스턴스를 수신하고, 콘텐츠 협상을 수행할 수 있도록 응답 객체에 컨텍스트를 추가하는 등 몇 가지 기능을 제공한다.

또한 wrapper는 적절한 경우 405 Method Not Allowed responses를 반환하고, 잘못된 입력으로 request.data에 액세스할 때 발생하는 ParseError 예외를 처리하는 등의 동작을 제공한다.

 

실행해보기

새로운 컴포넌트를 사용하여 뷰를 수정해보자

from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer


@api_view(['GET', 'POST'])
def snippet_list(request):
    """
    List all code snippets, or create a new snippet.
    """
    if request.method == 'GET':
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True)
        return Response(serializer.data)

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

인스턴스 view는 이전보다 개선되었다. 좀 더 간결해졌으며 코드는 Forms API로 작업할 때와 매우 유사하다. 또한 named status codes를 사용하여 응답의 의미가 더 명확해졌다.

이제 views.py 모듈의 개별 스니펫에 대한 view를 작성하자.

@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
    """
    Retrieve, update or delete a code snippet.
    """
    try:
        snippet = Snippet.objects.get(pk=pk)
    except Snippet.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    if request.method == 'GET':
        serializer = SnippetSerializer(snippet)
        return Response(serializer.data)

    elif request.method == 'PUT':
        serializer = SnippetSerializer(snippet, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    elif request.method == 'DELETE':
        snippet.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

일반 Django 뷰로 작업하는 것과 크게 다르지 않다.

requests나 responses를 더 이상 특정 콘텐츠 유형에 명시적으로 묶지 않는다는 점에 주목하라. request.data는 들어오는 json 요청을 처리할 수 있지만 다른 형식도 처리할 수 있다. 마찬가지로 response 객체는 데이터와 함께 반환되지만 한편으로는 REST framework가 응답을 올바른 콘텐츠 유형으로 렌더링하도록 한다.

'DRF Tutorial' 카테고리의 다른 글

DRF Tutorial 3: Class-based Views  (0) 2023.02.14
DRF Tutorial 2: Requests and Responses 2  (0) 2023.02.14
DRF Tutorial 1: Serialization 3  (0) 2023.02.14
DRF Tutorial 1: Serialization 2  (0) 2023.02.14
DRF Tutorial 1: Serialization 1  (0) 2023.02.13