이전 글에서 serializer까지 만드는 글이였다. 이제는 view를 짜주어서 JSON 파일을 반환해줘야 한다.
초창기에 장고는 FBV만 제공했으나 FBV는 함수로 정의하기에 직관적이고 구현하기 쉽다는 장점이 있지만, 확장성과 재사용성이 낮아 CBV를 제공하게 되었다. 하지만 CBV가 FBV를 완벽하게 대체하는 것은 아니므로 상황에 따라 적절한 방법으로 2가지 방법중에 골라서 view를 구현하면 될것 같다.
구성은 Django를 통해 구성했던 view에서 serializer를 추가해서 처리해준것뿐 동일하다. 클래스 기반 뷰이든 함수 기반 뷰이든 뷰가 실행하는 것은 함수이다. 우리가 View.as_view() 클래스 메소드를 사용하여 URL 정의에 뷰를 추가하면 이는 view라는 함수를 리턴한다.
우선 나는 CBV와 FBV두가지 다 구현해 보았다.
api/views.py
from django.http import JsonResponse
from django.views.decorators.csrf import csrf_exempt
from rest_framework.parsers import JSONParser
from api.models import Post
from api.serializers import PostSerializer
@csrf_exempt
def post_list(request):
if request.method == 'GET':
posts = Post.objects.all()
serializer = PostSerializer(posts, many=True)
return JsonResponse(serializer.data, safe=False)
elif request.method == 'POST':
data = JSONParser().parse(request)
serializer = PostSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data, status=201)
return JsonResponse(serializer.errors, status=400)
def post_detail(request, pk):
try:
post=Post.objects.get(pk=pk)
except Post.DoesNotExist:
return JsonResponse(status=404)
if request.method == 'GET':
serializer = PostSerializer(post)
return JsonResponse(serializer.data)
elif request.method == 'PUT':
data = JSONParser().parse(request)
serializer = PostSerializer(data=data)
if serializer.is_valid():
serializer.save()
return JsonResponse(serializer.data)
return JsonResponse(serializer.errors, status=400)
elif request.method == 'DELETE':
post.delete()
return JsonResponse(status=204)
APIView를 상속받아 용도에 맞는 클래스를 생성하여 사용하고, 클래스 내에 HTTP 메소드를 처리할 함수를 정의하여 사용한다.
/posts/ 에 대한 CBV
- get : 전체 posts 정보 조회
- post : 새로운 post 생성
/posts/<int:pk>/ 에 대한 CBV
- get : pk번 post 정보 조회
- patch : pk번 post 정보 변경
- delete : pk번 post 정보 삭제
api/urls.py
from django.urls import path
from api import views
from rest_framework.urlpatterns import format_suffix_patterns
urlpatterns = [
path('posts/', views.PostList.as_view()),
path('posts/<int:pk>', views.PostDetail.as_view())
]
urlpatterns = format_suffix_patterns(urlpatterns)
api/views.py
from django.http import Http404
from rest_framework.response import Response
from rest_framework.views import APIView
from api.models import Post
from api.serializers import PostSerializer
class PostList(APIView):
def get(self, request, format=None): # Post 전체 가지고 오기
posts = Post.objects.all()
serializer = PostSerializer(posts, many=True)
return Response(serializer.data, safe=False)
def post(self, request, format=None): # Post 작성하기
serializer = PostSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
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)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
def delete(self, request, pk, format=None): # 특정 Post 삭제
post = self.get_object(pk)
post.delete()
return Response(status=204)
pk값을 인자로 받아서 객체를 찾아서 존재하면 반환해주고 pk값에 해당하는 객체가 없으면 에러가 뜨게 해주는 함수이다.
반복되는 코드들을 줄여줘서 코드가 간결해지고 가독성이 높아지게 해주는 함수이다.
장고 공식 튜토리얼에 보면 CBV에서 필드로 항상 format=None을 작성해주는데 이게 하는 역할이 무엇인지 궁금했다
그래서 검색해 보니까 127.0.0.1:8000/api/posts/6.json과 같은 URL을 API에서 처리할 수 있게 해주며 또한 urls.py에
urlpatterns = format_suffix_patterns(urlpatterns)를 추가해 주어야 적용이 된다.
- 지금 찾아보니 별로 필요없다고 한다....ㅎㅎ