티스토리 뷰

Django에서 View를 만들어 웹 게시판에서 가장 기본 기능인 Create, Read, Update, Delete를 구현해보자.

 

DRF에서 뷰를 만드는 것은 순수 장고를 사용할때와 마찬가지로 함수형, 클래스형 2가지로 나눌 수 있다.

REST Framework는 API 뷰를 만드는데 2가지 wrapper를 제공한다.

  • 함수형 View: @api_view
  • 클래스형 View: APIView

wrapper에서는 뷰에서 Request 인스턴스를 수신하고, 해당 메소드를 인자로 전달해서 메소드에 맞는 로직 실행.

클래스형 View는 APIView, GenericView, ViewSet으로 추상화 단계를 높일 수 있는데 우선 APIView부터 알아보자.

 

1. 엔드포인트 구성(urls.py)

- pk(primary key) 정보가 필요없는 List, Crete를 수행하는 뷰

- pk 정보가 필요한 Detail, Update, Delete 뷰

2가지로 나누어 작성할 수 있다.

from django.urls import path
from news.api.views import article_list_create_api_view, article_detail_create_view

urlpatterns = [
    path("articles/", article_list_create_api_view, name="article-list"),
    path("articles/<int:pk>", article_detail_create_view, name="article-detail")
]

 

2-1. Article List/Create View 만들기

News Article List를 제공하는 기능과, List를 추가하는 기능은 하나의 View에서 처리할 수 있다

Function-Base View 이기 때문에 함수 내부에서 if 분기를 이용해 GET, POST 요청을 처리한다.

@api_view(["GET", "POST"])
def article_list_create_api_view(request):
    if request.method == "GET":
        articles = Article.objects.filter(active=True)
        serializer = ArticleSerializer(articles, many=True)
        return Response(serializer.data)

    elif request.method == "POST":
        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-2. Article Detail View 만들기

News Article의 세부 내용을 가져오고, 수정하고, 삭제하는 View를 정의한다

마찬가지로 Function-Base View 이기 때문에 함수 내부에서 if 분기를 이용해 GET, PUT, POST 요청을 처리한다.

@api_view(["GET", "PUT", "DELETE"])
def article_detail_create_view(request, pk):
    try:
        article = Article.objects.filter(pk=pk)
    except Article.DoesNotExist:
        return Response({"Error": {
            "code": 404,
            "message": "Article not found"
        }}, status=status.HTTP_404_NOT_FOUND)

    if request.method == "GET":
        serializer = ArticleSerializer(article)
        return Response(serializer.data)

    elif request.method == "PUT":
        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)

    elif request.method == "DELETE":
        article.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

 

 

3. Class-Based View

2번에서 만든 함수형 뷰를 클래스 기반의 뷰로 바꿔보자.

함수형 뷰와 달리 클래스 기반 뷰는 클래스를 선언하고 해당 클래스 내부에서 함수를 선언하여 처리한다.

get, post, put delete 등의 함수를 설정하여 사용한다.

APIView를 들어가보면 View 클래스를 상속하고 있는 것을 볼 수 있는데 View 클래스에서 http_method_names을 정의하고 있다.

http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
class ArticleListCreateAPIView(APIView):

    def get(self, request):
        articles = Article.objects.filter(active=True)
        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 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 = get_object_or_404(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 = get_object_or_404(pk)
        article.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

 

4. 모듈 설명

1) APIView

REST Framework는 Django View 클래스의 하위 클래스로 APIView 클래스를 제공한다.

3번에서 http_method_names를 설명할 때 한번 언급하였다. APIView 클래스가 View 클래스에 비해 가지는 장점은

 

- Request는 Django의 HttpRequest/Response 인스턴스가 아닌 REST Framework의 request/response 인스턴스가 된다

- APIException 예외케이스가 발견되면 적절한 response로 조정된다

- Incoming request를 authenticate하고, 적절한 권한 혹은 throttle(제한사항)을 체크한 후 실행한다

 

 

2) get_object_or_404

get_object_or_404 함수는 장고 모델을 첫번째 인자로 받고 (get_object_or_404(Article, pk)), get 함수에서 전달될 임의의 값을 키워드 인자로 받는다. 함수 이름과 마찬가지로 pk에 대응하는 객체가 존재하지 않으면 404 에러가 발생.

함수형 뷰에서는 try/except 구문으로 사용하였고, 클래스형 뷰에서는 get_object_or_404로 사용한다.

 

'Django' 카테고리의 다른 글

[Django] Cookie SameSite 이슈  (0) 2022.02.04
[Django] User Authenticate / 유저 인증  (0) 2022.01.30
[Django] Django ModelSerializer  (0) 2022.01.18
[Django] Django Serializers  (0) 2022.01.16
[Django] DRF - Django Rest Framework  (0) 2022.01.11
댓글