https://www.django-rest-framework.org/tutorial/2-requests-and-responses/#request-objects
이제부터 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