[DRF] VIEW - APIVIEW
오늘은 DRF에 view에 대해 정리를 해볼 차례이다.
django에서 view는 클라이언트 한테 들어온 요청에 대해서 어떻게 처리를 해줄지에 대해 정하는 것이며 MTV 패턴에서 Model, Template, View에서 view에 해당하는 부분이다. 장고에서는 MTV패턴이라고 하지만 보통은 MVC패턴이라고 불린다.
MVC는 Model, View , Controller이며 장고에서 view는 MVC에서 Controller에 해당하는 백엔드에 영역이다.
View를 정의하기에 앞서 우리는 클라이언트에 요청에 어떤식으로 요청, 응답을 해줄지에 대해 고민을 해봐야 한다.
HTTP통신에서는 중요한 여러가지의 메서드가 존재한다.
-
GET: 클라이언트가 서버에게 URL에 해당하는 자료의 전송을 요청한다.
-
HEAD: GET 요청으로 반환될 데이터 중 헤더 부분에 해당하는 데이터만 요청한다.
-
POST: 클라이언트가 서버에서 처리할 수 있는 자료를 보낸다. 예를 들어, 게시판에 글을 쓸 때 클라이언트의 문서가 서버로 전송되어야 한다. 멱등성을 보장하지 않는다.
-
PATCH: 클라이언트가 서버에게 지정한 URL의 데이터를 부분적으로 수정할 것을 요청한다.
-
PUT: 클라이언트가 서버에게 지정한 URL에 지정한 데이터를 저장할 것을 요청한다.
-
DELETE: 클라이언트가 서버에게 지정한 URL의 정보를 제거할 것을 요청한다.
-
TRACE: 클라이언트가 서버에게 송신한 요청의 내용을 반환해 줄 것을 요청한다.
-
CONNECT: 클라이언트가 특정 종류의 프록시 서버에게 연결을 요청한다.
-
OPTIONS: 해당 URL에서 지원하는 요청 메세지의 목록을 요청한다.
보통 Post, Get, Put, Delete를 많이 사용하며 순서대로 데이터베이스에 자료를 전송하는 방법이며, 데이터베이스에 있는 자료를 가지고 오는 방법이며, 지정한 URL로 데이터를 저장하는 것을 요청하는 방법이며, 데이터를 삭제하는것을 요청하는 방법이다.
필자는 문의사항에 대해서 api를 만들고 있기 때문에 보통 Post, Get, Put, Delete를 사용하게 될것이다.
문의사항을 생성하고, 원래 있던 문의사항을 불러오고, 문의사항을 수정하고, 문의사항을 삭제하는 방식으로 문의사항 게시판이 작동을 할 것이다.
여기까지가 일단 view에서 클라이언트가 서버에 요청, 응답을 할 때 처리해야 하는 방법을 작성해 놓았다.
이제 DRF에서 이를 어떻게 처리하는지를 보자.
DRF에 View에는 여러가지의 방법이 존재한다.
일단은 크게 함수형 View와 클래스형 View가 존재한다. 함수형 View는 재사용이 불편하다는 점에서 그냥 공식문서의 사이트를 올려놓고 공식문서에 함수형 View를 짜는 튜토리얼을 제공하니 그것을 한번 보는 것을 추천한다.
https://www.django-rest-framework.org/tutorial/2-requests-and-responses/
2 - Requests and responses - Django REST framework
From this point we're going to really start covering the core of REST framework. Let's introduce a couple of essential building blocks. REST framework introduces a Request object that extends the regular HttpRequest, and provides more flexible request pars
www.django-rest-framework.org
클래스형 View에는 APIView 방식, Mixins방식, GenericCBV방식, ViewSet방식이 있다. 여기에 순서대로 써놓은 이유는 오른쪽으로 갈수록 전에 클래스를 상속해서 점점 코드가 짧아지고 간편해지게 된다.
이것을 보기 좋게 나열해보면
APIView-->Mixins-->GenericCBV-->ViewSet
이 순서대로 전에 클래스를 상속해서 점점 코드가 간결하게 된다. 그렇기에 블로그에는 차례차례 작성을 할 예정이다.
일단 코드를 한번 살펴보자.
이전에 Serializer와 유효성 검증을 하면서 모델과 시리얼라이저에 대한 코드를 올려 놓았다. 어떤 모델을 설정했고, 시리얼라이저를 어떻게 만들었으며, 유효성검증을 어떻게 했는지 궁금하면 밑에 블로그를 보고 오면 된다.
https://srilankakim66.tistory.com/46
[DRF] Validation-유효성 검증
어제 건의사항 페이지를 만들기 위해서 api를 짯다. 몇일에 걸쳐 잠을 줄인 결과 api짜는 것이 이해가 되고 조금 수월해 졌다. 너무 뿌듯하다!!!!! 그렇기에 django drf에서 건의사항(Post라고 app을 만
srilankakim66.tistory.com
이제 APIView를 통해서 View를 살펴보자.
from django.shortcuts import render
from .models import Post
from .serializer import PostSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, viewsets
# Create your views here.
# 밑에 주석된 코드는 APIView로 작성한 view이다.
class PostList(APIView):
def get(self, request, format=None):
posts = Post.objects.all()
serializer = PostSerializer(posts, many=True)
return Response(serializer.data)
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)
class PostDetail(APIView):
def get_object(self, pk):
try:
return Post.objects.get(pk=pk)
except Post.DoesNotExist:
raise Http404
def get(self, request, pk, format=None):
post = self.get_object(pk)
serializer = PostSerializer(post)
return Response(serializer.data)
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)
def delete(self, request, pk, format=None):
post = self.get_object(pk)
post.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
일단 PostList를 통해서 포스트에 작성된 게시글을 가지고 오고, 생성하는 방식의 코드를 짜주었다. 즉 Get, Post방식에 대한 처리코드를 작성해 놓은것이다. PostList는 전체 글에 대해서 가지고 오고 Post를 생성하는 방법에 대해서 포괄적인 범위를 담당하는 api이다.
여기서 이제 각각의 포스트에 대해 세세하게 들어가기 위해선 PostDetail이라는 클래스를 만들어주어서 엔드포인트에 pk인 id값을 적어주면 그에 맞는 포스트를 하나씩 찾아서 데이터를 가지고 오고, 클라이언트가 만든 포스트를 데이터베이스에 저장하며, 클라이언트가 선택한 포스트를 삭제하는 방식으로 진행을 하게 된다.
여기서 다른 웹사이트를 생각해보자!!!
우리가 웹에서 검색을 할때를 생각해보면 보통 id값이 아닌 제목 혹은 작성자로 검색을 하는 것을 볼 수 있다. 그렇기에 우리는 Post 데이터를 가지고 올 때 id별로 말고 다른 컬럼 값을 주었을 때에도 그에 대한 데이터를 뽑을 수 있어야 한다.
그렇기에 밑에 그에 대한 코드를 작성해놨다. 필자가 만든 Post의 모델에는 id말고도 여러가지의 필드가 존재하는데 거기서 title을 예시로 코드를 짯다.
from django.shortcuts import render
from .models import Post
from .serializer import PostSerializer
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status, viewsets
# Create your views here.
class PostDetailTitle(APIView):
def get_object(self, title):
try:
return Post.objects.get(title=title)
except Post.DoesNotExist:
raise Http404
def get(self, request, title, format=None):
post = self.get_object(title)
serializer = PostSerializer(post)
return Response(serializer.data)
def put(self, request, title, format=None):
post = self.get_object(title)
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)
def delete(self, request, title, format=None):
post = self.get_object(title)
post.delete()
return Response(status=status.HTTP_204_NO_CONTENT)
get_object(self, title)라는 함수를 PostDetail 클래스 밑에 정의를 해서 우리가 엔드 포인트에 pk인 id값 말고도 다른 컬럼 값을 요청받아도 그에 대한 데이터를 호출 할 수 있게 API를 만든 것이다. @@
이것은 내가 만들어놓은 api에 큰 흐름이다. 솔직히 아직 필자도 모든 코드에 대해 이해가 잘 되지 않지만, 이 큰 흐름을 알고 어떻게 api를 짜야될지 머릿 속에 구상이 된다면 코드는 크게 문제가 되지 않는다. 그렇기에 View가 어떻게 돌아가는지 흐름을 이해하는데 초점을 두자!!!
이렇게 만들어 놓은 view를 가지고 이제 url로 보내줘야 하는데 url에 대한 코드 또한 살펴보자.
# api/urls.py
from django.urls import path, include
from rest_framework.urlpatterns import format_suffix_patterns
from .views import PostDetailTitle, PostList, PostDetail
from rest_framework.routers import DefaultRouter
# 밑에는 class view를 기반으로 할 때, 만들어줘야 하는 url방식이다.
urlpatterns = [
path('posts/', PostList.as_view()),
path('posts/<int:pk>/', PostDetail.as_view()),
path('posts/<str:title>',PostDetailTitle.as_view()) # endpoint에 title을 요청받아서 요청받은 title에 대한 데이터를 넘겨주는 url이다.
]
urlpatterns = format_suffix_patte
# backend/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('api/', include("api.urls")),
path('post/', include('post.urls')),
]
여기서 필자가 너무 친화적으로 블로그를 작성하지 않아서 장고 프로젝트를 어떻게 시작했고, 어떤 app만들었고 어떤 settings을 추가했는지에 대해 설명을 안했다.
요즘 프로젝트를 하면서 필자 또한 DRF에 대해서 처음 겪어보고 공부하면서 코드를 짜고 있기 때문에 시간이 없어서 어쩔 수 없......
지금 만들고 있는 JWT로 로그인과 회원가입, 건의사항 게시판 만드는 모든 코드를 올리고 보고 따라 할 수 있게끔 정리를 해서 꼭 올릴 예정이다!!! 좀만 기다려주시면 감사하겠습니다!!!
각설하고 필자가 만든 urls.py를 보면 urls도 2가지로 나누어져 있는 것을 볼 수 있다.
전체적으로 포스트를 볼 수 있는 'posts/' url과 세부적인 포스트를 볼 수 있는 'posts/<int:pk>'로 나누어져 있는 것을 볼 수 있다.
그리고 여기서 잠깐 추가적인 얘기를 하자면 장고에서는 as_view()로 postman과 같이 데이터가 어떻게 저장되고 어떻게 응답하는지를 볼 수 있는 내장 기능을 지원한다. 그렇기에 views.PostList.as_view(), views.PostDetail.as_view()에 as_view()는 Postman과 같이 어떻게 데이터가 요청, 응답하는지를 보기 위한 기능이라고 이해하는 것이 편하다.
이제 실제 api를 한번 보자. 장고에서 서버를 실행 해보자.
http://127.0.0.1:8000/post/posts/ 접속을 했을 때 작성을 할 수 있는 페이지가 나오는 것을 볼 수 있다.
username은 'ray' title은 '제목' content는 '내용' 이렇게 작성을 해보겠다.
이렇게 작성을 하고 POST버튼을 누르면
JSON형태로 POST가 보내지는 것을 볼 수 있다. 그러면 View함수에서 정의했듯이 POST 요청이 오게 되면 요청 온 데이터를 유효성검증을 끝내고 데이터 베이스에 저장을 하게 된다.
그러면 이제 http://127.0.0.1:8000/post/posts/1 url에 대한 api를 보자. 이 url은 PostDetail에 해당하는 url에 해당이 된다.
PostDetail View에서 작성을 했던 Get, Put, Delete가 존재하는 것을 볼 수 있다.
http://127.0.0.1:8000/post/posts/1에서 1에 대한 값이 궁금할 수 있는데 이것은 장고에서 모델을 만들 때 자동으로 만들어지는 Primary_Key이다.
즉 id인데 id는 저절로 생성되기에 Post를 하는 순서대로 1부터 쭉 unique한 값으로 자동으로 만들어진다. 그리고 이것을 나중에 코드를 짜다보면 pk라고 부르는데 이건 나중에 더 설명을 하겠다.
지금까지 APIView를 통한 post 건의사항 게시판을 작성하는 api를 짜봤다. 이제 view의 순서대로 진행 할텐데 앞으로 코드가 어떻게 더 간결해지고, 짧아지는지를 볼 수 있을 것이다.
@@++@@++