DRF Tutorial

DRF Tutorial 1: Serialization 3

waterclean101 2023. 2. 14. 11:39

시리얼라이저를 사용하여 일반 장고 뷰 작성하기

새로운 Serializer 클래스를 사용하여 몇 가지 API 뷰를 작성하는 방법을 살펴보자. 지금은 REST 프레임워크의 다른 기능을 사용하지 않고 일반 Django 뷰로 view를 작성할 것이다.

snippets/views.py 파일에 다음 코드를 작성한다

from django.http import HttpResponse, JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.parsers import JSONParser
from snippets.models import Snippet
from snippets.serializers import SnippetSerializer

API의 루트는 기존의 모든 스니펫을 나열하거나 새 스니펫을 생성하는 것을 지원하는 view가 될 것이다.

@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: csrf 방식을 간단히 해제 시키는 전처리기 

csrf란?

더보기

csrf란 사이트 간 요청 위조 즉, 인터넷 사용자(희생자)가 자신의 의지와는 무관하게 공격자가 의도한 행위(수정, 삭제, 등록 등)를 특정 웹사이트에 요청하게 만드는 공격이다. csrf를 통해 해커는 희생자의 권한을 도용하여 중요 기능을 실행하는 것이 가능하다.

 

CSRF 토큰이 없는 클라이언트에서 이 뷰에 게시할 수 있도록 하려면 뷰를 csrf_exempt로 표시해야 한다. 이 작업은 일반적으로 수행하지 않는 것이 좋지만 지금 당장은 튜토리얼 목적에 맞게 표시해준다.

다음으로 스니펫을 검색, 업데이트 또는 삭제하는 데 사용할 수 있는 개별 스니펫에 해당하는 뷰를 작성해준다.

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

 

snippets 디렉토리에 urls.py를 생성하고 작성한 뷰를 연결해준다. 

# snippets/urls.py

from django.urls import path
from snippets import views

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

또한 루트 url.py에 스니펫 앱의 url들을 연결해준다. 

# tutorial/urls.py

from django.urls import path, include

urlpatterns = [
    path('', include('snippets.urls')),
]

현재 제대로 처리하지 못하고 있는 몇 가지 엣지 케이스가 있다는 점에 주목할 필요가 있다. 잘못된 json을 보내거나 뷰에서 처리할 수 없는 메서드를 사용하여 요청을 하면 500 "서버 오류" 응답이 반환된다. 그래도 지금은 이 정도면 충분하다고 보고 다음으로 넘어가겠다.

 

웹 API에 대한 첫 테스트

이제 스니펫을 제공하는 샘플 서버를 시작할 수 있다.
셸을 다음 코드로 종료시킨 후에

quit()

장고 개발 서버를 열어준다.

python manage.py runserver

runserver를 하게 되면 로컬서버가 열린다

curl 또는 httpie를 사용하여 API를 테스트할 수 있다. Httpie는 파이썬으로 작성된 사용자 친화적 http 클라이언트다.
pip를 사용하여 httpie를 설치할 수 있다.

pip install httpie

 

http://127.0.0.1:8000/snippets/ 로 접근하면 Json response를 얻을 수 있다.

 

# http://127.0.0.1:8000/snippets/

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

 

또는 특정 스니펫의 ID를 참조하여 특정 스니펫을 가져올 수도 있다.

# http://127.0.0.1:8000/snippets/2/

HTTP/1.1 200 OK
...
{
  "id": 2,
  "title": "",
  "code": "print(\"hello, world\")\n",
  "linenos": false,
  "language": "python",
  "style": "friendly"
}

 

'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 2: Requests and Responses 1  (0) 2023.02.14
DRF Tutorial 1: Serialization 2  (0) 2023.02.14
DRF Tutorial 1: Serialization 1  (0) 2023.02.13