classPostForm(forms.ModelForm): classMeta: model = Post fields = '__all__'
# myapp/views.py
defpost_list(request): if request.method == 'POST': # 새 글 저장을 구현 form = PostForm(request.POST, request.FILES) if form.is_valid(): post = form.save() return JsonResponse(post) return JsonResponse(form.errors) else: # 목록 응답을 구현 return JsonResponse(Post.objects.all())
defpost_detail(request, pk): post = get_object_or_404(Post, pk=pk)
if request.method == 'PUT': # 특정 글 갱신을 구현 put_data = QueryDict(request.body) form = PostForm(put_data, instance=post) # put_data는 request.PUT같은 영할, instance넘어가면 수정하는것 (???) if form.is_valid(): post = form.save() return JsonResponse(post) return JsonResponse(form.errors) elif request.method == 'DELETE': # 특정 글 삭제를 구현 post.delete() return HttpResponse() else: # 특정 글 내용 응답을 구현 return JsonResponse(post)
뭔가 정형화되어있는 듯한 구현이지요? django rest framework는 REST API 구현을 도와주는 Class Based View를 제공해주는 프레임워크입니다. 다음과 같은 코드로 줄여볼 수 있겠습니다. 아래 코드는 위 코드와 동일한 동작을 수행하는 코드입니다.
CLI 프로그램에서 http 명령을 통해 사용하실 수 있어요. 다음은 HTTPie명령의 사용예입니다.
1 2 3 4 5
쉘> http GET 요청할주소 GET인자명==값 GET인자명==값 쉘> http --json POST 요청할주소 GET인자명==값 GET인자명==값 POST인자명=값 POST인자명=값 #json 방식 (디폴트임) 쉘> http --form POST 요청할주소 GET인자명==값 GET인자명==값 POST인자명=값 POST인자명=값 #multipartform방식 쉘> http PUT 요청할주소 GET인자명==값 GET인자명==값 PUT인자명=값 PUT인자명값 쉘> http DELETE 요청할주소 GET인자명==값 GET인자명==값
이 중에 POST요청은 2종류로 구분됩니다. 서버로 요청이 전달될 때, 전달 데이터를 어떻게 인코딩하느냐의 차이입니다.
--form 옵션 지정 시 : multipart/form-data 요청 : HTML Form과 동일합니다.
--json 옵션을 지정하거나 생략 시 : application/json 요청 : 요청 데이터를 JSON포맷으로 직렬화해서 전달합니다(request body에다가 실어서넘김.
GET/POST/PUT/DELETE 요청을 날려볼 서버가 필요한데, 우리는 아직 서비스를 만들지 않았어요. 그렇다고 해서 서버를 만들때까지 기다릴 순 없구요. httpbin.org 서비스로 쏴보겠습니다. API개발을 도와주는 서비스로서, 요청내역에 대한 상세정보를 응답으로 줍니다. 요청내역을 디버깅하고자 할 때 유용하게 사용하실 수 있습니다.
from django.http import HttpResponse, JsonResponse from django.http import QueryDict from django.shortcuts import get_object_or_404 from django.views.decorators.csrf import csrf_exempt from .models import Post from .forms import PostForm
@csrf_exempt #api서버에서 요청할떄는 csrf토큰없으므로 예외로줌 defpost_list(request): if request.method == 'GET': qs = Post.objects.all() data = [{'pk': post.pk, 'message': post.message} for post in qs] # 수동 JSON 직렬화!!, 직렬화란, 어떠한 객체를 문자열 형태로 변환함. return JsonResponse(data, safe=False) elif request.method == 'POST': form = PostForm(request.POST) if form.is_valid(): post = form.save() return HttpResponse(status=201) data = form.errors return JsonResponse(data, status=400)
@csrf_exempt defpost_detail(request, pk): post = get_object_or_404(Post, pk=pk)
if request.method == 'GET': return JsonResponse({'pk': post.pk, 'message': post.message}) elif request.method == 'PUT': put = QueryDict(request.body) form = PostForm(put, instance=post) if form.is_valid(): post = form.save() data = {'pk': post.pk, 'message': post.message} return JsonResponse(data=data, status=201) return JsonResponse(form.errors) elif request.method == 'DELETE': post.delete() return HttpResponse('', status=204)
URLConf 구현 : myapp/urls.py
1 2 3 4 5 6 7
from django.conf.urls import url from .views import post_list, post_detail
쉘> http :8000 # 목록 조회 쉘> http --form POST :8000 message="hello world" # 새 포스팅 등록 쉘> http :8000/1/ # 1번 포스팅 조회 쉘> http --form PUT :8000/1/ message="hello django" # 1번 포스팅 수정 쉘> http :8000/1/ # 1번 포스팅 수정 쉘> http DELETE :8000/1/ # 1번 포스팅 삭제 쉘> http :8000 # 목록 조회
django-rest-framework를 통한 API 구현 샘플
설치
1
pip3 install djangorestframework
settings.py 에 앱 추가
1 2 3 4
INSTALLED_APPS = [ # 중략 'rest_framework', ]
위에서 django의 ModelForm/View를 통해 직접 구현했던 API 인터페이스를 django-rest-framework를 통해 구현해봅시다.
아래의 PostViewSet은 Class Based View로서 위에서 장고로 구현했던 모든 기능을 일괄 제공해줍니다.
구현
모델 : myapp/models.py
1 2 3 4
from django.db import models
classPost(models.Model): title = models.CharField(max_length=100)
Serializer : myapp/serializers.py (Form과 유사기능)
1 2 3 4 5 6 7
from rest_framework import serializers from .models import Post
classPostSerializer(serializers.ModelSerializer): classMeta: model = Post fields = '__all__'
뷰 : myapp/views.py
1 2 3 4 5 6 7
from rest_framework import viewsets from .models import Post from .serializers import PostSerializer