Rest Framework
이번장에서는 Django의 Rest Framework을 이용해 CRUD(Create, Retrieve, Update, Delete)를 할 수 있는 RESTful 서비스를 구현해 보겠습니다.
Rest Framework을 사용하기 위해서는 pip 를 이용해서 해당 모듈을 먼저 설치해야 합니다.
(본 강의는 http://www.django-rest-framework.org 의 튜토리얼을 기반으로 작성되었습니다. 좀 더 자세한 내용을 원하시면 해당 사이트의 API를 참조하시기 바랍니다.)
가. Rest Framework 설치
터미널(CMD) 창에서 아래 명령어를 입력합니다.
- pip install djangorestframework
나. 프로젝트 생성 및 기본설정
1.프로젝트 및 앱 생성 터미널에서 pjt_bbs 프로젝트를 생성하고 내부에 bbs 앱을 같이 생성해 주기 위해서 아래 명령어를 순서대로 입력합니다.
- django-admin startproject pjt_bbs
- cd pjt_bbs
- python manage.py startapp bbs
2.모델생성 models.py 파일을 열고 아래와 같이 모델을 정의합니다.
- 프로젝트디렉토리/bbs/models.py
from django.db import models
class Bbs(models.Model):
created = models.DateTimeField(auto_now_add=True)
title = models.CharField(max_length=100, blank=True, default='')
author = models.CharField(max_length=20, blank=True, default='')
pw = models.CharField(max_length=12, blank=True, default='')
content = models.TextField()
class Meta:
ordering = ('created',)
3.앱등록 settings.py 에 생성한 앱을 등록합니다.
- 프로젝트디렉토리/pjt_bbs/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework',
'bbs',
]
4.admin에 모델등록
admin 에 생성한 모델을 등록해줍니다.
- 프로젝트디렉토리/bbs/admin.py
from django.contrib import admin
from bbs.model import Bbs
class BbsAdmin(admin.ModelAdmin):
list_display=('title','author','created',)
admin.site.register(Bbs, BbsAdmin)
5.url설정
요청 url에 대한 설정을 합니다. 먼저 프로젝트 url 파일을 수정합니다.
- 프로젝트디렉토리/pjt_bbs/urls.py
from django.conf.urls import url, include
from django.contrib import admin
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^bbs/', include('bbs.urls')),
]
그리고 bbs 앱 디렉토리에 urls.py 파일을 생성하고 설정해줍니다.
- 프로젝트디렉토리/bbs/urls.py
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from bbs import views
urlpatterns = [
url(r'^$', views.bbs_list),
url(r'^(?P<pk>[0-9]+)/$', views.bbs_detail),
]
urlpatterns = format_suffix_patterns(urlpatterns)
6.migration
이제 설정한 파일들을 실제 적용하기 위해 migration 명령어를 실행해 줍니다.
- python manage.py makemigrations # bbs 하위 디렉토리에 마이그레이션 파일 생성
- python manage.py migrate # 정의한 Bbs 모델로 데이터베이스 테이블 생성
다. 개발
1.Serializer 작성
Serializer 는 데이터를 직렬화(마치 스트림데이터처럼 변경) 해줍니다. 이 직렬화를 통해서 메모리상에 있는 변수와 값의 세트를 json 데이터로 변환해서 사용할 수 있게 됩니다. serializers.py 파일을 생성하고 아래와 같이 입력해줍니다.
- 프로젝트디렉토리/bbs/serializers.py
from rest_framework import serializers
from bbs.models import Bbs
class BbsSerializer(serializers.ModelSerializer):
# ModelSerializer 를 이용해서 아래와 같이 짧은 코드로 직렬화 필드를 정의할 수 있다
class Meta:
model = Bbs
fields = ('id','title','author','pw','content')
# 신규 Bbs instance를 생성해서 리턴해준다
def create(self, validated_data):
return Bbs.objects.create(**validated_data)
# 생성되어 있는 Bbs instance 를 저장한 후 리턴해준다
def update(self, instance, validated_data):
instance.title = validated_data.get('title', instance.title)
instance.author = validated_data.get('author', instance.author)
instance.pw = validated_data.get('pw', instance.pw)
instance.content = validated_data.get('content', instance.content)
instance.save()
return instance
2.View 작성
위에서 작성한 serializer를 이용해서 웹으로 부터 요청을 받을 View 파일을 작성합니다. url에서 bbs/ 로 끝나는 요청이 GET일경우 목록으로 처리하고, POST로 들어오면 입력으로 처리합니다. 그리고 bbs/ 다음에 숫자값이 입력되어 있을경우(예를들어 bbs/15)에 GET일 경우 한개의 데이터, PUT은 수정, DELETE 는 삭제처리를 해줍니다. views.py 파일을 열고 아래와 같이 작성해줍니다.
- 프로젝트디렉토리/bbs/views.py
from rest_framework import status
from rest_framework.decorators import api_view
from rest_framework.response import Response
from bbs.models import Bbs
from bbs.serializers import BbsSerializer
# 요청 url 인 bbs/ 에 대해서 urls.py 에 정의된 view.bbs_list 가 호출된다.
@api_view(['GET', 'POST'])
def bbs_list(request, format=None):
if request.method == 'GET':
bbs = Bbs.objects.all()
serializer = BbsSerializer(bbs, many=True) # many 값이 True 이면 다수의 데이터 instance를 직렬화할수 있다
return Response(serializer.data)
elif request.method == 'POST':
serializer = BbsSerializer(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)
# 요청 url 인 bbs/번호 에 대해서 urls.py 에 정의된 view.bbs_detail 이 호출된다
@api_view(['GET', 'PUT', 'DELETE'])
def bbs_detail(request, pk, format=None):
try:
bbs = Bbs.objects.get(pk=pk)
except Bbs.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND)
if request.method == 'GET':
serializer = BbsSerializer(bbs)
return Response(serializer.data)
elif request.method == 'PUT':
serializer = BbsSerializer(bbs, 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':
bbs.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
다. 개발내용 테스트
1.서버실행
프로젝트 디렉토리에서 서버를 실행합니다.
- python manage.py runserver
2.포스트맨을 통한 데이터입력 요청
우선 데이터 입력처리 확인을 위해 포스트맨을 열고 아래와 같이 입력합니다.
주소 : http://127.0.0.1:8000/bbs/
Method : POST
Headers : application/json
Body (type=Raw) :
{
"title":"title test",
"author":"michael",
"pw":"qwer1234",
"content":"i am here"
}
3. 브라우저에서 데이터 요청
몇개 데이터를 더 입력한 후 브라우저를 통해 목록을 요청하면 아래와 같이 Django restframework 에서 지원하는 json 데이터 페이지가 출력됩니다. 웹 브라우저를 통해 요청하면 아래와 같이 완성된 형태의 페이지가 보여지게 되고, ajax 나 모바일 앱을 통해 요청을 하면 데이터만 받아서 사용할 수 있게 됩니다.
라. 클래스 기반 뷰처리
이번에는 코드를 조금 수정해서 기존 함수기반의 뷰 처리를 클래스 기반으로 변경해 보겠습니다. 클래스 기반으로 변경하는 이유는 rest framework 라이브러리 클래스에 CRUD에 대한 기본처리가 정의되어 있기 때문에 더 짧은 코드로 CRUD 를 완성할수 있기 때문입니다. 먼저 views.py 파일을 열고 아래와 같이 코드전체를 수정합니다.
1.views 수정
- 프로젝트디렉토리/bbs/views.py
# 클래스 기반의 Rest CRUD 처리
from bbs.models import Bbs
from bbs.serializers import BbsSerializer
from rest_framework import generics
# generics 에 목록과 생성 API 가 정의되어 있다
class BbsList(generics.ListCreateAPIView):
queryset = Bbs.objects.all()
serializer_class = BbsSerializer
# generics 에 상세, 수정, 삭제 API가 정의되어 있다
class BbsDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = Bbs.objects.all()
serializer_class = BbsSerializer
2.urls 수정
- 프로젝트디렉토리/bbs/urls.py
from django.conf.urls import url
from rest_framework.urlpatterns import format_suffix_patterns
from bbs import views
urlpatterns = [
# 함수형 처리시 호출되는 함수
# url(r'^$', views.bbs_list),
# url(r'^(?P<pk>[0-9]+)/$', views.bbs_detail),
# 클래스를 호출하고 해당클래스의 as_view() 함수를 호출
url(r'^$', views.BbsList.as_view()),
url(r'^(?P<pk>[0-9]+)/$', views.BbsDetail.as_view()),
]
urlpatterns = format_suffix_patterns(urlpatterns)
이제 브라우저에서 테스트 주소를 다시 입력해보면 이전과 동일하게 동작하는 것을 확인할 수 있습니다.
이와 같이 Django의 Rest Framework을 사용할 경우 클래스기반으로 코드를 작성하게 되면 더 짧은 코드로 빠른 시간안에 완성도 높은 결과물을 만들 수 있게됩니다.