2. Requests and Responses

hyuckhoon.ko·2023년 9월 28일
0

1. Requests objects

HttpRequest를 확장한 Request가 사용되는데, request 파싱을 쉽게 도와준다. 핵심은 request.data다.
장고 튜토리얼에서 봤었던 request.POST 보다 request.data를 사용하자.


2. Response objects

DRF에서는 Response 객체를 사용한다.
TemplateResponse의 한 형식으로써 렌더링되지 않은 내용을 가져다가 content negotiaion을 통해 클라이언트에 반환할 올바른 내용 유형을 결정한다.


3. Status codes

DRF는 좀 더 명시적인 상태 코드를 제공한다.
예를 들어,HTTP_400_BAD_REQUEST같이 말이다.
단순히 숫자 정보만 담긴 상태코드를 리턴하는 것보다 더 좋은 방법이다.


4. Wrapping API views

DRF는 2개의 wrapper를 제공한다.

1) @api_view 데코레이터

FBV(Funtion Based View)에 사용된다.

2) APIView 클래스

CBV(Class Based View)

이러한 wrapper가 제공하는 기능은 무엇이 있을까?

  • API가 Request 인스턴스들을 입력을 받는다는 것을 명시적으로 확인
  • Response에 context를 추가할 수 있게 되어 content
  • 허용되지 않는 메서드의 요청등에 대한 응답이 가능(405 Method Not Allowed)
  • 잘못된 형식의 입력에 대해 request.data 수준에서 파싱 에러를 일으킬 수 있음

5. 적용해보기

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
    - 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)


@api_view(["GET", "PUT", "DELETE"])
def snippet_detail(request, pk):
    """
    - Retrieve
    - Update
    - Delete
    """

    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(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)

많은 변화가 있다.

  • request.data를 통한 request 데이터 값 접근
    request.data는 request의 json 요청들을 처리할 수도 있지만, 다른 형식의 요청들도 처리할 수 있다.
    이전 챕터에서는 명시적으로 아래와 같이 파싱했어야 했다.
    data = JSONParser().parse(request)
  • status.HTTP_204_NO_CONTENT 같은 명시적인 HTTP 상태코드

6. json이 아닌 다른 형식은 어떻게 처리할까?


### views.py
def snippet_list(request, format=None):

def snippet_detail(request, pk, format=None):


### urls.py
from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from snippets import views


urlpatterns = [
    path("snippets/", views.snippet_list),
    path("snippets/<int:pk>/", views.snippet_detail),
]

urlpatterns = format_suffix_patterns(urlpatterns)

Accept 헤더를 사용하여 다른 형식의 데이터를 받아보자.

pip install httpie

Request JSON

>>> http http://127.0.0.1:8000/snippets.json


HTTP/1.1 200 OK
Allow: GET, OPTIONS, POST
Content-Length: 319
Content-Type: application/json
Cross-Origin-Opener-Policy: same-origin
Date: Thu, 28 Sep 2023 07:13:28 GMT
Referrer-Policy: same-origin
Server: WSGIServer/0.2 CPython/3.10.10
Vary: Accept, Cookie
X-Content-Type-Options: nosniff
X-Frame-Options: DENY

[
    {
        "code": "foo = \"bar\"\n",
        "id": 1,
        "language": "python",
        "linenos": false,
        "style": "friendly",
        "title": ""
    },
    {
        "code": "print(\"hello, world\")\n",
        "id": 2,
        "language": "python",
        "linenos": false,
        "style": "friendly",
        "title": ""
    },
    {
        "code": "print(\"hello, world\")",
        "id": 3,
        "language": "python",
        "linenos": false,
        "style": "friendly",
        "title": ""
    }
]

Request HTML

http http://127.0.0.1:8000/snippets/ Accept:text/html   

Browsability

이를 통해 DRF는 클라이언트가 요청한 content type에 기반한 응답을 제공해 준다. DRF를 사용해보면 알 수 있듯이, 클라이언트가 웹 브라우저에서 DRF를 사용할 때 HTML 형식의 representation으로 리턴한다.

web-browsable API는 이점이 많다.
개발을 할 때 API를 디버깅하고 사용하기에도 편하다.

0개의 댓글