이 포스트는 인프런의 "Django REST Framework 핵심사항"강의를 듣고 제작하였습니다.
이번 글에서는 저번 글에서 다뤘던 개념에서 더 나아가 코드를 직접 보면서 GenericView
들 중 일부에 대해 어떻게 활용하는 지에 대해서 간단하게 다뤄보려고 한다.
본격적인 시작전에 우선 우리가 사용할 URL
과 그 URL
에 사용할 View
를 생각을 해놔야 한다.
일단 우리가 만들 웹사이트는 블로그의 형식이고 이에 따라서 글의 리스트페이지, 글의 상세페이지, 댓글 작성 등을 할 수 있어야된다.
View
의 이름에서 알 수 있듯이 queryset의 리스트
를 보여주는 것이 ListAPIView
이고 그 중 하나의 인스턴스
에 대해서만 보여줄 때 사용하는 것이 RetrieveAPIView
이다.
이에 대해서 한번 알아보도록 하자.
우선은 글의 리스트를 보여주는 페이지와 글의 상세페이지를 보여주는 페이지를 구현하기 위해서는 각각의 URL
들에 대해서 GenericView
들을 매칭시켜주어야 한다.
다음과 같이 urls.py
에서 각각의 URL
과 그에 따른 View
를 작성해주자.
#api2 > urls.py
from django.urls import path, include
from api2 import views
urlpatterns = [
path('post/',views.PostListAPIView.as_view(),name='post-list'),
path('post/<int:pk>',views.PostRetrieveAPIView.as_view(),name='post-detail'),
]
as_view()
메소드에 대한 설명은 이 글에 자세히 나와있으니 자세한 설명은 생략한다.
쉽게 말해서 Class형 View를 사용하기 위한 진입메소드
라고 생각하면 된다.
DRF
에서는 url-name
과 관련된 기본 규칙이 있다.
꼭 아래의 규칙을 지킬 필요는 없지만 url-name
은 해당 url
의 동작을 유추할 수 있는 단어로 짓는 것이 좋다. ViewSet
+ router
의 조합을 사용한다면 자동적으로 아래의 규칙에 따라 url-name
이 정의되고 동작 시 사용된다.
DRF의 url-name 규칙
{ model 명 }
-list
:pk
가 없는 기본url
ex ) post/
{ model 명 }
-detail
:pk
를 사용하는url
ex ) post/1/
바로 코드부터 확인해보도록 하자.
#api2 > views.py
from rest_framework.generics import ListAPIView, RetrieveAPIView, CreateAPIView
from api2.serializers import PostSerializer, CommentSerializer
from blog.models import Post, Comment
class PostListAPIView(ListAPIView):
queryset=Post.objects.all()
serializer_class=PostSerializer
class PostRetrieveAPIView(RetrieveAPIView):
queryset=Post.objects.all()
serializer_class=PostSerializer
urls.py
에서 각각 url
과 대응시킨 view
들에 대한 코드들이다. 매우 간결한 것을 알 수 있는데 이것이 바로 GenericView
의 장점이라고 할 수 있을 것이다. 기본 제공하는 기능만 사용한다면 이렇게만 작성해도 완성이다.
각각 ListAPIView
와 RetrieveAPIView
를 상속받아 만들어졌으며 queryset
과 serilalizer_class
가 정의
된 것을 확인할 수 있다. 이 두 개에 대한 정보는 반드시 있어야된다.
GenericView
의 간단한 동작흐름을 살펴보면 다음과 같다.
db
로부터데이터
들을 가져옴 -> 그데이터
를serializer
->serializer
된데이터
를 반환
즉, queryset = db로부터 가져온 data들
, serializer_class = serializer 방법 / 형식
으로 이해하면 된다.
코드를 살펴보기전에 간략하게 ListAPIView
와 RetrieveAPIView
에 대해서 알아보려고 한다.
저번 글에서 소개했던 것과 같이 cdrf.com에 DRF
에 존재하는 클래스들의 정보들이 잘 정리되어있어 이를 활용해도 된다. 이 글에서는 파일을 직접 접근해서 ListAPIView
와 RetrieveAPIView
의 차이점에 대해서 알아보려고 한다.
#rest_framework > mixins.py
class ListModelMixin:
"""
List a queryset.
"""
def list(self, request, *args, **kwargs):
queryset = self.filter_queryset(self.get_queryset())
#페이지에 관한 부분
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
#rest_framework > mixins.py
class RetrieveModelMixin:
"""
Retrieve a model instance.
"""
def retrieve(self, request, *args, **kwargs):
instance = self.get_object()
serializer = self.get_serializer(instance)
return Response(serializer.data)
각각의 Mixin
클래스에서 list()
와 retrieve()
메소드들을 확인할 수 있다.
이를 통해 알 수 있는 차이점은 다음과 같다.
list와 retrieve의 차이점
list( ) retrieve( ) queryset을 가져오는 메소드 filter_queryset get_object serializer의 인자 many = True Default ( many = False )
queryset
:list
는queryset
전체에 대해서 가져오고retrieve
는queryset
의인스턴스 하나
에 대해서만 가져온다.
get_serializer
:list
는many=True
로 지정하여queryset
전체의serilaizer
된 값을 반환하지만
retrieve
는하나의 인스턴스
에 대해서만serializer
된 데이터를 반환한다.
get_object
와get_serlializer
의 동작방식에 대해서는GenericAPIView
에서 찾아볼 수 있다.
이러한 차이점으로 인해 ListAPIView
와 RetrieveAPIView
이 각각 다른 동작을 하는 것이라고 생각하면 된다.
serializer
에 관한 이야기가 많이 나오고 있는데 쉽게 생각하면 사용자에게 정보를 보여줄 출력포맷을 정하는 것으로 이해할 수 있다.
코드와 함께 살펴보자.
#api2 > serializers.py
from rest_framework import serializers
from blog.models import Post, Comment
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = ['id', 'title', 'image', 'like', 'category']
PostSerializer
는 ModelSerializer
클래스를 상속받아 만들어졌으며 클래스의 내용은 일단 Meta클래스
로 정의했다. Serializer
는 상황에 따라 더욱 세분화하여 나타낼 수도 있으며 이에 대해서는 다음에 자세히 다뤄보도록 하겠다.
이렇게 urls.py
, views.py
, serializers.py
를 정의하고 나면 대략적인 구현이 끝났다고 보면 된다. 이제 서버를 실행시켜보도록 하자.
이제 서버를 실행해서 우리가 작성했던 구현했던 API
에 대한 URL
에 접속해서 살펴보자.
사진과 같이 post/
접근하면 이렇게 DB
에 저장되었던 post에 대한 정보가 리스트
로 잘 출력되는 것을 알 수 있다.
그리고 post/1/
로 접근하면 이렇게 id
와 pk
가 서로 같은 하나의 인스턴스
가 출력되는 것을 확인할 수 있다.
ListAPIView
는queryset
에 대한리스트
를,RetrieveAPIView
는 그 중하나의 인스턴스
를 사용자에게 반환한다.
- 이 두
GenericView
가 다르게 동작하는 이유는 상속받은Mixin
클래스에서의 동작방식이 다르기 때문이다.