들어가기

Django 에서 REST API 를 위한 프레임워크가 있는데 그것이 DRF (Django REST Framework) 이다

실제 Django 에서 PUT, PATCH, DELETE 를 제대로 지원하지 않기 때문에 RESTful 하게 작업하려면 DRF가 필요하다

최근에 알게 된 것이지만 PUTPATCH는 비슷하면서 다른 뜻이다. PUT은 데이터 전체를 바꾸는 것을 뜻하고, PATCH는 일부를 바꾸는 것을 뜻한다. PUT은 입력하지 않은 데이터는 NULL로 바꾼다는 뜻이니 조심하자!

시작하기

설치

$ pip install djangorestframework

설정

먼저 INSTALLED_APPS 에 넣어주자

settings.py

INSTALLED_APPS = [
    ...
    'rest_framework',
]

DRF에는 많은 기능이 있지만 나는 내가 먼저 필요한 기능만 정리하겠다
(아마 필요하다면 계속 업데이트가 될 것이다)

request.data (PUT, PATCH)

Django 에서 POST로 온 폼 데이터는 request.POST.get('name') 형태로 불러 올 수 있었지만 PUT과 PATCH는 지원하지 않는다. DRF에서는 이를 request.data로 불러올 수 있다

views.py

from rest_framework.decorators import api_view

@api_view(['PATCH'])
def changePassword(request):
  pw = request.data.get('password')
  ...

이런식으로 쉽게 불러 올 수 있다

Testing

테스트를 진행할 때 나같은 경우는 Client 를 사용해서 response를 테스트하는데 request.data를 못 읽는다
그래서 DRF에서 지원하는 APIClient를 이용해야한다

tests.py

from django.test import TestCase
from rest_framework.test import APIClient

class APITest(TestCase):
  def test_change_password(self):
    client = APIClient()
    response = client.patch('/login', {'new_password': 'password'})
    self.assertEqual(response.status_code, 200)

직렬화(Serializer)

이제 DRF의 메인 기능인 직렬화를 해보자

API 통신의 데이터 타입은 주로 JSON 으로 한다. 하지만 Django에서 Model 데이터는 보통 Queryset 이라는 복잡한 타입으로 되어있다. 이런 타입을 JSON으로 바꾸기 위해선, 파이썬 네이티브 타입으로 변환해주는 직렬화(Serializer) 란 작업이 필요하다

Serializer 생성

DRF의 Serializer는 Django의 Form과 사용방법이 거의 비슷하다

models.py

class Pet(models.Model):
  name = models.CharField(max_length=50)
  age = models.InteagerField()

위와 같은 Pet 모델을 직렬화 할 것이다


먼저 App 폴더 안에 serializers.py라는 파일을 만들어주자

serializers.py

from rest_framework import serializers

class PetSerializer(serializers.Serializer):
    name = serializers.CharField(max_length=50)
    age = serializers.IntegerField()

JSON 변환과정

이제 이 Serializer를 불러와서 JSON으로 반환해주자

views.py

from .serializers import PetSerializer

def getPet(request):
  pet = Pet.objects.get(pk=1)
  serializer = PetSerializer( pet )

_id가 1인 펫을 QuerySet 이라는 복잡한 Django type에서 Python의 Dictionary로 변환하였다

이제 이것을 전송하기 위해 문자열로 변환해주자

from .serializers import PetSerializer
from rest_framework.renderers import JSONRenderer
from django.http import HttpResponse

def getPet(request):
  pet = Pet.objects.get(pk=1)
  serializer = PetSerializer(pet)
  data = JSONRenderer().render(serializer.data)
  return HttpResponse(data)

Array 직렬화

위는 하나의 객체만 직렬화 하는 과정이다. 이번엔 여러개의 객체 인스턴스를 배열에 담아 직렬화 해보자

views.py

from .serializers import PetSerializer

def getPets(request):
  pets = Pet.objects.all()
  serializer = PetSerializer( pets, many=True )

many=True 만 같이 넣어주면 다수의 Pet 모델이 들어온 것을 인식한다

하지만 현재의 serializer.data는 이런식의 데이터이다

[ {'name': 'pet_name'},{ ...} ]

json은 배열이 아니라 object 형태로 작성해야하기 때문에 이 배열을 object 에 담아 문자열로 변환시키자

views.py

from .serializers import PetSerializer

import json

def getPets(request):
  pets = Pet.objects.all()
  serializer = PetSerializer( pets, many=True )
  data = json.dumps({'pets':serializer.data})
  return HttpResponse(data)

이번엔 내장모듈인 json을 활용해 인코딩하였다

이제 아래와 같은 문자열이 반환될 것이다

{ 'pets' : [ {...}, ... ] }