DRF - Tutorial 2

21251 단어 drfdrf

1. Request 와 Response


Request objects

DRF에서는 HttpRequest 를 확장한 Request 객체를 제공한다. Request 객체는 더욱 유연한 request parsing 기능을 제공한다.

쓰임새는 request.POST와 비슷하나 request.POST는 POST메소드로 들어온 요청에 한해서만 쓰일 수 있지만 request.data는 POST, PUT, PATCH까지 사용할 수 있다.

Response objects

Response 객체는 TemplateResponse 의 타입으로서 렌더링 되지 않은 content를 불러와 콘텐츠협상(negotiation content)의 과정을 거쳐 클라이언트에게 리턴할 올바른 content type으로 변환한다.

여기서 잠깐 콘텐트 협상이란?

 

2. Status Code


일반 Django에서는 Response할 상태코드를 숫자만 보내는데, DRF에서는 status module의 HTTP_400_BAD_REQUEST 처럼 보다 명확한 상태코드를 보낸다.

 

3. Wrapping API Views


DRF에서는 2개의 Wrapper를 제공하는데, 하나는 함수기반뷰(FBV)에 사용되는 @api_view 와 클래스기반뷰(CBV)에 사용되는 APIView 이다.

2개의 wrapper 모두 Request 객체를 수신 하는지 확인하고, content negotiation을 할 수 있도록Response 객체에 context를 추구하는 기능등을 가지고 있다.

Functional Based View

기본 Django View

# views.py
@csrf_exempt
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 JsonResponse(serializer.data, safe=False)

    elif request.method == 'POST':
        data = JSONParser().parse(request)
        serializer = SnippetSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data, status=201)
        return JsonResponse(serializer.errors, status=400)
@csrf_exempt
def snippet_detail(request, pk):
    """
    Retrieve, update or delete a code snippet.
    """
    try:
        snippet = Snippet.objects.get(pk=pk)
    except Snippet.DoesNotExist:
        return HttpResponse(status=404)

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

    elif request.method == 'PUT':
        data = JSONParser().parse(request)
        serializer = SnippetSerializer(snippet, data=data)
        if serializer.is_valid():
            serializer.save()
            return JsonResponse(serializer.data)
        return JsonResponse(serializer.errors, status=400)

    elif request.method == 'DELETE':
        snippet.delete()
        return HttpResponse(status=204)

FBV의 @api_view 데코레이터를 이용한 View

# views.py

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)
@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)
  • Request에 담겨져있는 데이터를 따로 parsing하지 않고 request.data를 이용하여 json data로 처리할 수 있어다.
  • status 객체를 이용하여 보다 명확한 상태코드를 처리할 수 있다.

 

4. Adding optional format suffixes to our URLs


View 함수에 키워드 아규먼트를 추가함으로써 Client가 원하는 Content Type으로 제공할 수 있다.

방법

  • 위의 view 함수에 format 매개변수를 추가하면된다.
# views.py
@api_view(['GET', 'POST'])
def snippet_list(request, format=None):
    ...

@api_view(['GET', 'PUT', 'DELETE'])
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.SnippetList.as_view()),
    path('snippets/<int:pk>/', views.SnippetDetail.as_view()),
]

# urlpatterns이 `format_suffix_patterns` 모듈을 참조하여 사용자에게 보여질 content type을 결정
urlpatterns = format_suffix_patterns(urlpatterns)
  • json 또는 탐색가능한 api
>>> http http://127.0.0.1:8000/snippets/3.json
>>> http http://127.0.0.1:8000/snippets/3.api

좋은 웹페이지 즐겨찾기