DRF 2-7 Class Based Views

Grace Goh·2022년 10월 27일
0

Django Rest Framework

목록 보기
8/36

지금까지는 함수형 views를 썼는데 앞으로는 Class형 views를 작성한다.

함수형 views

# articles/views.py

from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework.generics import get_object_or_404
from articles.models import Article
from articles.serializers import ArticleSerializer


# 함수형 뷰
@api_view(['GET', 'POST'])
def articleAPI(request):
    if request.method == 'GET':
        articles = Article.objects.all()
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)
    elif request.method == 'POST': # 디시리얼라이즈
        serializer = ArticleSerializer(data = request.data) 
        if serializer.is_valid():
            serializer.save() 
            # print(serializer.data)
            # print(request.data['title'])
            return Response(serializer.data, status=status.HTTP_201_CREATED) # 완성된 데이터를 보내준다.
        else:
            print(serializer.errors)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 
            # 개발 단계에선 편리하지만 front에 표시하는 건 보안상 좋지 않다.


@api_view(['GET', 'PUT', 'DELETE'])
def articleDetailAPI(request, article_id):
    if request.method == 'GET':
        # return Response(article) 이렇게는 할 수 없고
        # article = Article.objects.get(id=article_id) # 1004를 저장
        article = get_object_or_404(Article, id=article_id)
        serializer = ArticleSerializer(article)
        return Response(serializer.data)
    elif request.method == 'PUT':
        # 위 상세페이지처럼, 복사해서 가져와서 수정을 해줘야 한다.
        article = get_object_or_404(Article, id=article_id)
        serializer = ArticleSerializer(article, data=request.data) 
        # (원래data:읽기, 나중에들어온data) 앞의data를 뒤data로 바꾸어주는 것.
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
    elif request.method == 'DELETE':
        article = get_object_or_404(Article, id=article_id)
        article.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

클래스형 views

https://www.django-rest-framework.org/tutorial/3-class-based-views/ 에서 복붙해서 시작해도 괜찮다.

from rest_framework import status
from rest_framework.response import Response
from rest_framework.decorators import api_view
from rest_framework.views import APIView # 추기
from rest_framework.generics import get_object_or_404
from articles.models import Article
from articles.serializers import ArticleSerializer
from drf_yasg.utils import swagger_auto_schema # 추가


class ArticleList(APIView):
    def get(self, request, format=None):
        articles = Article.objects.all()
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)

	@swagger_auto_schema(request_body=ArticleSerializer)
    def post(self, request, format=None):
        serializer = ArticleSerializer(data = request.data) 
        if serializer.is_valid():
            serializer.save() 
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            print(serializer.errors)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
            

class ArticleDetail(APIView):
    def get(self, request, article_id, format=None):
        article = get_object_or_404(Article, id=article_id)
        serializer = ArticleSerializer(article)
        return Response(serializer.data)

    def put(self, request, article_id, format=None):
        article = get_object_or_404(Article, id=article_id)
        serializer = ArticleSerializer(article, data=request.data) 
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data)
        else:
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, article_id, format=None):
        article = get_object_or_404(Article, id=article_id)
        article.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

generic class-based views를 쓰면 기본 기능은 빨리 만들 수 있다. 토이프로젝트 등 빨리 만들어 테스트할 때는 mixins 등을 적극적으로 사용해도 되지만 커스터마이징이 어렵고 trade-off가 있다.

프로젝트generic은 사용하지 않고 위와 같이 (APIView)를 상속 받아 사용하는 Class Based Views(CBV)를 사용한다.

CBV의 유용한 기능

# articles/views.py

...
from drf_yasg.utils import swagger_auto_schema # 추가

class ArticleList(APIView):
    def get(self, request, format=None):
        articles = Article.objects.all()
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)
        
    # 추가 (ArticleSerializer 명세에 맞춰 전송할 것)
    @swagger_auto_schema(request_body=ArticleSerializer) 
    def post(self, request, format=None):
        serializer = ArticleSerializer(data = request.data) 
        if serializer.is_valid():
            serializer.save() 
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        else:
            print(serializer.errors)
            return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST) 



데코레이터 swagger_auto_schema를 추가하면 http://127.0.0.1:8000/swagger/ 에서 자세한 명세를 볼 수 있다. ('title required' 등..)

Try it out을 눌러 POST 요청을 할 수 있다.

Postman에서도 같은 POST 요청 결과가 확인된다.
Swagger를 통해서도 편리하게 테스트해볼 수 있다.

frontend와 backend가 나눠져서 테스트를 하다 보면 어디서 에러가 발생했는지 찾는 게 복잡할 때가 많다.
SwaggerPostman을 통해 찾아보면 HTTP status 코드와 함께, {body} 내 key값 오타 등 사소한 에러들을 확인할 수 있다.

profile
Español, Inglés, Coreano y Python

0개의 댓글