DRF 3 - Class-based view : APIView (News api 3편)

Joey Lee·2020년 7월 9일
0

Django REST Framework

목록 보기
4/16

아래 사례는 Udemy의 "The complete Guide to Django Restframework and Vue JS" 강의 중 Section3의 : Django REST Framework - Level One의 내용을 요약정리한 것입니다.

앞서 Function-based View로 짠 것과 동일한 역할을 하는 코드를 Class-based View로 짜 봤습니다. ListCreateAPIView는 사실상 함수형 코드와 거의 유사하다. DetailAPIView는 get_object 메소드를 추가하여 사용한다는 점이 큰 차이이다. 클래스형 뷰이기 때문에 함수를 메소드로 지정하여, 재활용할 수 있기 때문이다.

2. Views.py 전체 코드

1) ArticleListCreateAPIView

from rest_framework.views import APIView
from rest_framework.generics import get_object_or_404

class ArticleListCreateAPIView(APIView):

    def get(self, request):
        articles = Article.objects.filter(active=True)
        serializer = ArticleSerializer(articles, many=True)  
        # queryset many=True, Model instance면 없어도 됨.
        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)

2) ArticleDetailAPIView

class ArticleDetailAPIView(APIView):
    
    def get_object(self, pk):
        article = get_object_or_404(Article, pk=pk)
        return article
    
    def get(self, request, pk):
        article = self.get_object(pk)
        serializer = ArticleSerializer(article)
        return Response(serializer.data)
    
    def put(self, request, pk):
        article = self.get_object(pk)
        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, pk):
        article = self.get_object(pk)
        article.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

[Debug를 통한 코드 이해]

  • get_object()메소드를 통해서 pk값이 2인 Article 인스턴스를 리턴
  • self는 ArticleDetailAPIView object를 의미함
  • self.get_object()를 통해 pk값이 2인 Article 인스턴스를 article 변수에 담음.
> /Users/seungholee/udemy_drf/newsapi/news/api/views.py(38)get_object()-><Article: Joh...are publising>
(Pdb) article
<Article: John Titor First articled we are publising>

/Users/seungholee/udemy_drf/newsapi/news/api/views.py(43)get()
(Pdb) self
<news.api.views.ArticleDetailAPIView object at 0x10332c310>
(Pdb) self.get_object(2)
<Article: John Titor How to be CEO it's tough>

3. 임포트한 모듈 이해

1) APIView

REST 프레임워크는 Django View 클래스의 하위 클래스로 APIView 클래스를 제공한다. APIView 클래스는 View 클래스와 아래와 같은 점에서 다른 부분이 있다.

  • Request는 Django의 HttpRequest 인스턴스가 아닌 REST 프레임워크의 request인스턴스가 됨
  • Django의 HttpResponse가 아닌 REST 프레임워크의 Response를 반환
  • APIException 예외케이스가 발견되면 적절한 response으로 조정됨
  • Incoming request를 authenticate하고, 적절한 권한 혹은 throttle(제한사항) 체크한 실행함

이 외에는 APIView 클래스는 View클래스를 사용하는 것과 동일하다. Incoming request는 .get()이나 .post()와 같은 적절한 핸들러 메서드로 전달된다.

2) get_object_or_404)

get_object_or_404 함수는 Django Model을 첫번째 인자로 받고, get() 함수에서 전달될 임의의 값을 키워드 인자로 받는다. 만약, 객체가 존재하지 않으면 Http404(page not found)를 띄운다.

article = get_object_or_404(Article, pk=pk)

4. Function-based view와 비교

  • 엔드포인트 숫자와 각 엔드포인트의 역할은 완전히 동일하고, 동일한 결과물을 리턴함
  • 다만, 차이점은 1) Function-based에서는 하나의 View에서 if request.method로 GET/DELETE/UPDATE를 분리한다면, Class-based에서는 def get/delete/update를 명시해 주기에 가독성이 더 좋음
  • Function-based에서는 try/except로 특정 객체가 존재하지 않을 때 예외 처리를 했다면, Class-based에서는 def get_object(self, pk)로 처리를 함
profile
안녕하세요!

0개의 댓글