본문 바로가기

Python/Django

[Django REST framework] 2. Requests and Responses

https://www.django-rest-framework.org/tutorial/2-requests-and-responses/#request-objects

 

2 - Requests and responses - Django REST framework

From this point we're going to really start covering the core of REST framework. Let's introduce a couple of essential building blocks. REST framework introduces a Request object that extends the regular HttpRequest, and provides more flexible request pars

www.django-rest-framework.org

이제부터 REST framework의 코어를 다뤄보자.

Request objects

HttpRequest -> Request

  : 더 유연한 request parsing이 가능

  : request.data 속성을 통해 arbitrary data를 다룰 수 있음

Response objects

JsonResponse -> Response

  : client가 요청한 content type으로 render할 수 있음

Status codes

from rest_framework import status 를 통해

HTTP_400_BAD_REQUEST와 같은

명확한 status module을 사용할 수 있다

Wraping API views

wrappers는 다음과 같은 기능을 제공한다:

  1. Request instances를 view에서 받았는지 확인하고, Response에 context를 더해 content neotiation을 peform

  2. 405 Method Not Allowed responses나 exception handling과 같은 에러처리 기능

 

REST framework는 2개의 wrappers를 제공한다:

  1. @api_view: decorator for working with function based views

  2. APIView: class for working with class-based views

Views 수정

위를 참고하여 snippets/views.py를 수정해보자

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

@api_view(['GET', 'POST'])
def snippet_list(request):
    """
    List all code snippets, or create new snippet.
    """
    if request.method == 'GET': # snippets 모두 불러오기
        snippets = Snippet.objects.all()
        serializer = SnippetSerializer(snippets, many=True) # queryset을 serialize 하기
        return Response(serializer.data) # json으로 return

    elif request.method == 'POST': # snippet 새로 만들기
        serializer = SnippetSerializer(data=request.data) # request.data를 통해 어떤 데이터도 가져올 수 있음
        if serializer.is_valid(): # 성공
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED) # 명확한 status reponse 가능
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) # 실패

@api_view(['GET', 'PUT', 'DELETE'])
def snippet_detail(request, pk):
    """
    Retrieve, update or delete a code snippet.
    """
    try:
        snippet = Snippet.objects.get(pk=pk) # 특정 snippet 가져오기
    except Snippet.DoesNotExist: # 일치하는 snippet이 없을 경우
        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)

optional format suffixes를 URLs에 추가하기

reponses가 더이상 하나의 content type에 국한되지 않기에

API endpoint에 format suffixes를 지원을 추가하자

예를 들어, http://example.com/api/items/4.json와 같은 URL의 뒤를 보면, json format을 지원한다는 것을 알 수 있다.

 

2가지를 스탭이 필요하다.

1. format suffixes를 urls에 추가하자

2. 각각의 view의 parameter에 format을 추가하자

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

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

urlpatterns = format_suffix_patterns(urlpatterns) # format suffix
snippets/views.py
def snippet_list(request, format=None):
# ...
def snippet_detail(request, pk, format=None):

테스트하기!

> python manage.py runserver

Accept header로 reponse format을 컨트롤해보자

format suffix를 뒤에 붙여서 읽어들일 수도 있다.

> http http://127.0.0.1:8000/snippets.json  # JSON sunffix
> http http://127.0.0.1:8000/snippets.api  # Browsable API suffix

 

이와 비슷하게, request format을 컨트롤할 수 있다: Content-Type header

POST using form data
POST using JSON