안녕세계
[장고 AtoZ] Django REST Framework - CBV(APIView) 본문
[장고 AtoZ] Django REST Framework - CBV(APIView)
Junhong Kim 2018. 2. 7. 18:27안녕하세요!
이번 포스팅에서는 DRF APIView 사용법을 알아보도록 하겠습니다.
지난 포스팅에서는 ModelViewSet을 상속받아서 간단하게 기본 CRUD와 Custom API를 만들 수 있었는데요.
이번에는 이러한 기본 CRUD들을 APIView라는 것을 상속받아서 매우 유연한 API를 만들어 보겠습니다.
자, 그럼 시작해 볼까요!?
APIView도 CBV(Class-Based-View)와 FBV(Function-Based-View) 두가지를 방법을 제공하는데요..
blog App 에서는 DRF ViewSet으로 만들었고,
이번에는 post App을 새로 생성하여 CBV를 만들어 보겠습니다.
PostApp을 생성해주세요.
$ django-admin startapp post
post app을 생성한 뒤 post 디렉토리 하위에 urls.py, serializers.py 파일을 생성하면 아래와 같은 구조가 됩니다.
그리고 먼저 장고 프로젝트 디렉토리(tutorial)로 이동해서 base.py에 post를 추가해주세요.
(추가적으로 우리가 웹브라우저에서 API 호출을 할 때 Web UI 와 JSON 형식 두가지로 보이는데
JSON 형식으로만 보이도록 REST_FRAMEWORK 옵션을 아래와 같이 삽입해주세요.
[tutorial/settings/base.py]
이제 post 앱으로 가서 model을 작성합니다.
blog앱과 다른 점이라면 message 대신 title이라고 명시했습니다.
from django.db import models
class Post(models.Model):
title = models.TextField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
그리고 모델에 대한 시리얼라이져를 생성합니다.
from rest_framework import serializers
from .models import Post
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'
그리고 이제 view를 만들 차례입니다.
[post/view.py]
우리는 두개의 클래스를 만들건데요.
두개의 클레스를 만드는 이유는 하나는 목록에 대한 view, 하나는 특정 객체에 대한 view 입니다.
먼저 목록에 대한 view를 만들어보겠습니다.
from django.http import Http404
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Post
from .serializers import PostSerializer
class PostList(APIView):
"""
게시물 생성
/post/
"""
def post(self, request, format=None):
serializer = PostSerializer(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)
"""
게시물 조회
/post/
"""
def get(self, request, format=None):
queryset = Post.objects.all()
serializer = PostSerializer(queryset, many=True)
return Response(serializer.data)
APIView를 상속 받고, post 요청은 post 함수를 정의 / get 요청은 get 함수를 정의합니다.
def post()
요청 받은 데이터(request.data)를
if 시리얼라이즈가 유효하면
저장한 뒤
응답으로 201 상태와 시리얼라이즈 데이터를 반환합니다.
유효하지 않으면 400 에러를 반환합니다.
def get()
Post의 모든 객체를
시리얼라이즈해서
응답으로 시리얼라이즈 데이터를 반환하빈다.
class PostDetail(APIView):
def get_object(self, pk):
try:
return Post.objects.get(pk=pk)
except Post.DoesNotExist:
raise Http404
"""
특정 게시물 조회
/post/{pk}/
"""
def get(self, request, pk):
post = self.get_object(pk)
serializer = PostSerializer(post)
return Response(serializer.data)
"""
특정 게시물 수정
/post/{pk}/
"""
def put(self, request, pk, format=None):
post = self.get_object(pk)
serializer = PostSerializer(post, data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
"""
특정 게시물 삭제
/post/{pk}/
"""
def delete(self, request, pk, format=None):
post = self.get_object(pk)
post.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
APIView를 상속 받고,
get, put, delete 요청에 해당하는 함수를 정의합니다.
def get_object()
pk에 해당하는 Post 객체를 반환합니다.
없으면 404 에러를 발생합니다.
def get()
pk에 해당하는 객체를 get_object() 를 통해 반환 받습니다.
이를 시리얼라이즈하여
시리얼라이즈 데이터를 반환합니다.
def post
pk에 해당하는 객체를 get_object() 를 통해 반환 받습니다.
해당 객체를 요청받은 데이터로 시리얼라이즈 합니다.
if 시리얼라이즈가 유효하면
시리얼라이즈를 저장하고
시리얼라이즈 데이터를 반환합니다.
아니면 400에러 응답을 합니다
def delete
pk에 해당하는 객체를 get_object() 를 통해 반환 받습니다.
해당 객체를 삭제합니다.
응답으로 204 응답을 합니다.
위 작업을 진행한 뒤 url을 맵핑합니다.
from django.urls import path
from . import views
urlpatterns = [
path('', views.PostList.as_view()),
path('<int:pk>/', views.PostDetail.as_view())
]
두가지 url을 맵핑해야하는데
클래스 개수만큼 하나는 목록 리스트를 위한, 또 하나는 특정 객체를 위한 뷰입니다.
특정 객체를 위한 뷰 url을 정의할 때 <int:pk> 라고 되어있는데 여기서 pk는 함수를 정의할 때와 동일해야 합니다.
그리고 장고 프로젝트 url에 post 앱을 추가합니다.
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls')),
path('post/', include('post.urls')),
]
그럼 이제 DRF의 CBV로 API를 만드는데 성공했습니다.
서버를 실행하기전에, 우리는 새로운 post 모델을 정의하였으므로 makemigration과 migrate를 진행합니다.
makemigration
$ python manage.py makemigrations --settings=tutorial.settings.local
migrate
$ python manage.py migrate --settings=tutorial.settings.local
run server
$ python manage.py runserver --settings=tutorial.settings.local
서버가 실행됬으면 이제 잘 적용되었는지 확인해봅시다!
GET /post/
최초에는 아무런 데이터가 없기 때문에 빈 배열이 넘어오네요.
POST /post/
body에 title를 작성한 뒤 데이터를 생성해줍시다 (저는 2개를 생성하겠습니다)
GET /post/
데이터를 생성한 뒤 다시 조회해 보니 두개가 잘 저장되었네요.
GET /post/{pk}
특정 id의 게시물 조회도 잘되네요!
DELETE /post/{pk}
특정 id를 제거해봅시다. 공백이 반환되군요.
PUT /post/{pk}
수정도 진행해봅시다! body에 타이틀을 입력하고 요청하세요! 수정된 값이 잘 반환되네요
GET /post/
수정과 삭제가 잘 됬는지 마지막으로 확인이 잘 되었네요!
(API 호출시 에러가 날경우 url 마지막에 '/' 를 작성했는지 다시한번 확인해주세요)
이로써 DRF CBV로 API만들기를 마치도록 하겠습니다 ㅎㅎ
CBV로 viewSet과 동일한 기능을 하는 API를 만들
다음 포스팅에서는 동일한 기능을 하는 FBV를 만들어보도록 하겠습니다.
감사합니다.!
'Server > Django' 카테고리의 다른 글
[Django] Custom command 만들기 (0) | 2018.04.30 |
---|---|
[장고 AtoZ] Django REST Framework - FBV(@api_view) (0) | 2018.02.08 |
[장고 AtoZ] Django REST Framewrok - ViewSet(Custom) (0) | 2018.02.06 |
[장고 AtoZ] Django REST Framewrok - ViewSet(Params) (0) | 2018.02.06 |
[장고 AtoZ] Django REST Framewrok - ViewSet (0) | 2018.02.06 |