먼저 Django 에서는 views.py를 통해 HTTP와 소통하게 된다. view는 FBV, CBV등으로 나뉠 수 있는데, APIView는 CBV에 해당하고 Viewset은 Helper class에 해당한다.
from django.shortcuts import render
from .models import Post
from rest_framework import viewsets
from .serializers import PostSerializer
class PostViewSet(viewsets.ModelViewSet):
queryset = Post.objects.all()
serializer_class = PostSerializer
먼저 viewset은 APIView와 다르게 List와 Detail 부분의 queryset과 serializer_class가 동일하다는 것에 착안하여 그 두 부분을 한번에 표현한다는 것에서 의의가 있습니다.
viewsets는 조회만 할 수 있게 하려면 ReadOnlyModelViewSet을 이용하고 생성, 조회, 수정, 삭제가 가능하려면 ModelViewSet을 이용해야 합니다.
위의 예시에서는 Post와 Get, Delete, Put 모두 가능할 수 있도록 ModelViewSet을 이용한 것을 볼 수 있습니다.
from django.contrib import admin
from django.urls import include, path
from rest_framework import routers
from post import views
router = routers.DefaultRouter()
router.register(r'posts', views.PostViewSet)
urlpatterns = [
path('', include(router.urls)),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
path('admin/', admin.site.urls),
]
이 파일의 urls.py는 app에 있는 urls.py가 아닌 setting.py와 같은 폴더에 들어있는 파일입니다.
urls.py는 APIView와 많이 다르게 느껴질 수 있는 부분인 라우터를 이용하고 있습니다.
Viewset class를 이용하게 되면 URL을 설정하지 않고 view를 Router에 등록하여 자동으로 URL에 연결될 수 있도록 해줍니다.
위를 보면 register posts를 해줌으로써 posts라는 페이지를 path('')과 연결해 주었다는 것을 알 수 있습니다.
from rest_framework.response import Response
from rest_framework.views import APIView
from .models import Post
from .serializers import PostSerializer
class PostListAPIView(APIView):
def get(self, request):
serializer = PostSerializer(Post.objects.all(), many=True)
return Response(serializer.data)
def post(self, request):
serializer = PostSerializer(data=request.data)
if serializer.is_valid():
serializer.save()
return Response(serializer.data, status=201)
return Response(serializer.errors, status=400)
APIView는 ViewSet과 다르게 하나의 URL에 대해서만 처리할 수 있으므로 저는 PostDetail class는 만들지 않고 PostList로 get과 post만 처리를 하였습니다.(PostList class는 Get으로 모든 Post한 API를 불러오고, JSON 형식으로 POST를 할 수 있습니다.)
APIView는 Response를 통해 urls.py에 전달하여 URL과 연동시킬 수 있고, 상태는 201,400,200 처럼 status를 지정하여 설정할 수 있습니다.
유의할 점은 get, post를 할 때 모두 마지막에 Response를 안해주면 urls.py에 값을 전달하지 못하기 때문에 꼭 Response를 해주어야 합니다.
from django.contrib import admin
from django.urls import include, path
from post import views
urlpatterns = [
path('post/', views.PostListAPIView.as_view()),
path('post/<int:pk>/', views.PostDetailAPIView.as_view()),
path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
path('admin/', admin.site.urls),
]
urls.py는 ViewSet과 다르게 라우팅을 할 framework를 찾지 않고 as_view()로 라우팅을 해주게 됩니다. as_view()는 인스턴스를 생성하고 dispatch() method를 호출하게 되는데, dispatch method는 들어온 class가 get인지 post인지 등등을 구별하고 인스턴스내에서 해당 메소드의 요청을 받아들이는 역할을 한다.