DRF는 API의 List View에서 페이지네이션의 구현을 위해 별도의 클래스를 제공한다.
permission과 비슷하게, pagination도 프로젝트의 settings.py단에서 global하게 pagination을 설정할 수 있다.
종류는 이렇게 세가지가 있는데, 가장 많이 쓰이는건 역시 PageNumberPagination이다. PageNumberPagination이 정말 좋은건, 해당 페이지의 next page와 previous page가 Response의 body에 담겨 온다는 것.
1) settings.py
DRF 공식문서에 나와있는 다음의 코드를 붙여넣기 한다.
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 3 # 원래는 100으로 되어있지만, 우리는 3만 하도록 한다.
}
2) pagination을 실습할 때에는 미리 전에 인스턴스를 여러개 만들어 놓는 것이 좋다. 나는 review 6개를 미리 만들어두었다. 페이지네이션이 생긴 리스트가 무리 없이 작동할 것이다.
3) permission때도 그랬듯, 내가 직접 custom하여 Pagination을 해보자.
api/pagination.py를 생성하여 다음을 작성한다.
from rest_framework.pagination import PageNumberPagination
# 맨땅에 헤딩할 수는 없으니 당연히 PageNumberPagination 클래스를 임포트하면서 시작한다
class SmallSetPagination(PageNumberPagination):
page_size = 3
이 pagination.py를 작성한 후에는 당연히 처음에 settings.py에 작성한 global한 pagination은 주석처리하거나 삭제한다.
4) views.py에 와서 임포트할 차례이다.
from rest_framework import generics
from rest_framework import permissions
from rest_framework.exceptions import ValidationError
from rest_framework.generics import get_object_or_404
from ebooks.models import Ebook, Review
from ebooks.api.permissions import IsAdminUserOrReadOnly, IsReviewAuthorOrReadOnly
from ebooks.api.serializers import EbookSerializer, ReviewSerializer
from ebooks.api.pagination import SmallSetPagination
# 이렇게 내가 커스터마이징한 pagination을 임포트한 후,
class EbookListCreateAPIView(generics.ListCreateAPIView):
queryset = Ebook.objects.all()
serializer_class = EbookSerializer
permission_classes = [IsAdminUserOrReadOnly]
pagination_class = SmallSetPagination
# pagination이 필요한 EbookListCreateAPIView에 이 코드를 추가해준다.
5) 여기까지하면 정말 잘됐다고 느꼈겠지만, 딱 하나 더 중요한 것이 있다. 실행은 잘될건데, 아마도 터미널에는 "unordered한 object_list에 대한 pagination이 inconsistent result를 산출할수도 있다"는 경고 메시지를 보내고 있을 것이다. 따라서 우리는 ordered하게 해당 리스트를 설정해준다.
방금 전 수정한 views.py에서
class EbookListCreateAPIView(generics.ListCreateAPIView):
queryset = Ebook.objects.all().order_by('-id')
# 이렇게 order_by를 추가해준다.
# 인자를 negative 값으로 넣어준 것은 가장 최근의 것이 1페이지로 오게 하는 방식을 선호하기 때문이다.
serializer_class = EbookSerializer
permission_classes = [IsAdminUserOrReadOnly]
pagination_class = SmallSetPagination
references:
https://www.django-rest-framework.org/api-guide/pagination/#pagenumberpagination