안녕세계

[장고 AtoZ] Django REST Framework - CBV(APIView) 본문

[장고 AtoZ] Django REST Framework - CBV(APIView)

Junhong Kim 2018. 2. 7. 18:27
728x90
반응형

안녕하세요!

이번 포스팅에서는 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를 만들어보도록 하겠습니다.


감사합니다.!




728x90
반응형
Comments