함수기반 views와 비슷하게 api를 작성한 지난 글에 이어서 클래스 기반 view를 통해 api를 만들어서 보낼 수 있다. 초기 설정이나 model, serializer 등은 지난 글에서 작성했던 것 그대로 이용하면 된다. 이 글에서 달라지는 것은 view랑 url 정도이다.
지난 번에도 말했듯이 view를 작성하는 방법에는 함수로 작성하는 방법과 클래스로 작성해서 내부 메서드로 함수를 작성하는 방법이 있다. 지난 번 내용과 동일한 동작을 수행하는 클래스를 작성해보면 다음과 같다.
...
from rest_framework.views import APIView
# Create your views here.
class ArticleAPIView(APIView):
def get(self, request):
articles = Article.objects.all()
serializer = ArticleSerializer(articles, many=True)
return Response(serializer.data)
def post(self, request):
serializer = ArticleSerializer(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 ArticleDetails(APIView):
def get_object(self, id):
try:
return Article.objects.get(id = id)
except Article.DoesNotExist:
return Response(status=status.HTTP_404_NOT_FOUND )
def get(self, request, id):
article = self.get_object(id)
serializer = ArticleSerializer(article)
return Response(serializer.data)
def put(self, request, id):
article = self.get_object(id)
serializer = ArticleSerializer(article, 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, id):
article = self.get_object(id)
article.delete()
return Response(status = status.HTTP_204_NO_CONTENT)
코드는 대부분 비슷한데 함수 기반으로 작성했을 때는 HTTP 메서드를 if request.method == 'POST' 이런식으로 작성했던 부분들을 클래스 내부 함수들로 만들어 주었다. 또한 ArticleDetails 클래스에서는 get_object라는 함수를 만들어서 이후의 get, put, delete 동작을 수행할 때 객체를 불러오는 역할을 해줄 수 있도록 해주었다. 지난 글에서 제대로 이해했다면 위의 view는 같은 내용을 함수에서 클래스 기반으로 바꿔준 것을 쉽게 알 수 있을 것이다.
urls.py에도 다음과 같이 작성해주면 된다.
from django.contrib import admin
from django.urls import path
from .views import ArticleAPIView, ArticleDetails
urlpatterns = [
path('article/', ArticleAPIView.as_view()),
path('detail/<int:id>/', ArticleDetails.as_view()),
]
as_view() 메서드를 통해서 클래스를 view로 불러올 수 있다.
함수 기반 api나 view를 잘 이해했으면 클래스 기반도 크게 다른 점이 없다는 점을 알 수 있을 것이다. 오히려 함수 기반이 더 직관적이고 쉽게 느껴질 수도 있다. 하지만 클래스를 이용하는 데에는 이유가 있다. 바로 Generic view 라는 것 때문이다. 제네릭 view를 이용하면 자주 사용하는 형태에 대해서 미리 만들어둔 view들을 제공하기 때문에 훨씬 간단하고 편리하게 사용할 수 있다.
제네릭 클래스 기반 뷰 (Generic Class-Based View)
generic으로 클래스 기반 뷰를 짜면 다음과 같이 된다.
...
from rest_framework import generics, mixins
# Create your views here.
class GenericAPIView(generics.GenericAPIView, mixins.ListModelMixin, mixins.CreateModelMixin, mixins.UpdateModelMixin, mixins.RetrieveModelMixin, mixins.DestroyModelMixin):
serializer_class = ArticleSerializer
queryset = Article.objects.all()
lookup_field = 'id'
def get(self, request, id = None):
if id:
return self.retrieve(request)
else:
return self.list(request)
def post(self, request):
return self.create(request)
def put (self, request, id=None):
return self.update(request, id)
def delete(self, request, id):
return self.destroy(request, id)
먼저 부모 클래스로 generics.GeneralAPIView를 불러와주고, GET 메서드를 위해 ListModelMixin, POST메서드를 위해 CreateModelMixin, PUT 메서드를 위해 UpdateModelMixin, Delete 메서드를 위해 DestroyModelMixin을 상속받는다. 또한, 하나의 article 객체를 detail 페이지에서 처럼 보기 위해 RetrieveModelMixin도 상속 받는다. 이후 lookup_field를 지정해서 id를 기준으로 get, put, delete 할 수 있도록 해준다.
아래는 urls.py에서 연결해준 것이다.
from django.contrib import admin
from django.urls import path
from .views import GenericAPIView
urlpatterns = [
path('generic/article/<int:id>/', GenericAPIView.as_view()),
]
이렇게 하면 http://127.0.0.1:8000/generic/article/ 또는 http://127.0.0.1:8000/generic/article/1/ 과 같은 링크에서 기본적으로 제공받는 폼을 이용해서 POST, PUT, GET, DELETE가 다 가능한 것을 확인할 수 있다. APIView를 이용한 클래스 기반보다 정돈된 html 폼도 제공해주고 있다.
마찬가지로 postman 앱에서도 같은 동작을 할 수 있다.
'TIL > Python | Django' 카테고리의 다른 글
2021.8.9 TIL : [Django] DRF 4 - View Sets & routers (0) | 2021.08.09 |
---|---|
2021.8.7 TIL : [Django] DRF 3 - authentication (0) | 2021.08.07 |
2021.8.5 TIL : [Django] DRF(Django Rest Framework) 1 - 함수기반 api (0) | 2021.08.06 |
2021.7.23 TIL : [Django] ORM의 select_related/prefetch_related, forms.py에서 지정한 form을 css로 디자인하기, 외부 DB 연동하기 (0) | 2021.07.23 |
2021.7.16 TIL : [Python] 기초 문법8 - 클래스 상속 (0) | 2021.07.17 |
댓글