지난 포스트에서는 viewset에서의 pagination을 소개했었다. 그러나 프로젝트를 진행하다 보면서 viewset을 사용하지 않고 커스텀하기 쉬운 APIview를 통해서 뷰를 짰다. 따라서 APIview에서는 다르게 pagination을 적용해줘야 했다.
PageNumberPagination이 가장 흔하기 때문에 PageNumberPagination을 사용할 것이다.
views.py
class MemoPagination(PageNumberPagination):
page_size_query_param = 'limit'
우선 views에 PageNumberPagination를 import한다.
views.py
class MemoList(APIView):
pagination_class = MemoPagination
serializer_class = MemoSerializer
def get(self, request, format=None, *args, **kwargs):
instance = Memo.objects.all()
serializer = self.serializer_class(instance, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
pagination_class을 설정해주었지만 api 테스트를 해보면 아직 페이징이 적용되지 않을 것이다. APIView는 viewset과는 다르게 조금 더 추가를 해주어야 한다.
views.py
class MemoList(APIView):
pagination_class = MemoPagination
serializer_class = MemoSerializer
@property
def paginator(self):
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
else:
pass
return self._paginator
def paginate_queryset(self, queryset):
if self.paginator is None:
return None
return self.paginator.paginate_queryset(queryset,
self.request, view=self)
def get_paginated_response(self, data):
assert self.paginator is not None
return self.paginator.get_paginated_response(data)
def get(self, request, format=None, *args, **kwargs):
instance = Memo.objects.all()
page = self.paginate_queryset(instance)
if page is not None:
serializer = self.get_paginated_response(self.serializer_class(page,
many=True).data)
else:
serializer = self.serializer_class(instance, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
이제 API에서 "page"나 "limit"이라는 키를 통해 query parameter로 넘겨주어서 페이징을 컨트롤할 수 있다.
그러나 페이징이 필요한 API가 여러개가 있다면 위와 같은 코드들은 수없이 반복 될 것이다. 따라서 단순히 반복 작업을 하기 보다는 mixin을 써주어서 코드를 단순화 할 수 있다.
pagination.py
class PaginationHandlerMixin(object):
@property
def paginator(self):
if not hasattr(self, '_paginator'):
if self.pagination_class is None:
self._paginator = None
else:
self._paginator = self.pagination_class()
else:
pass
return self._paginator
def paginate_queryset(self, queryset):
if self.paginator is None:
return None
return self.paginator.paginate_queryset(queryset,
self.request, view=self)
def get_paginated_response(self, data):
assert self.paginator is not None
return self.paginator.get_paginated_response(data)
views.py
from rest_framework.pagination import PageNumberPagination
from .pagination import PaginationHandlerMixin
class MemoPagination(PageNumberPagination):
page_size_query_param = 'limit'
class MemoList(APIView, PaginationHandlerMixin):
pagination_class = MemoPagination
serializer_class = MemoSerializer
def get(self, request, format=None, *args, **kwargs):
instance = Memo.objects.all()
page = self.paginate_queryset(instance)
if page is not None:
serializer = self.get_paginated_response(self.serializer_class(page,
many=True).data)
else:
serializer = self.serializer_class(instance, many=True)
return Response(serializer.data, status=status.HTTP_200_OK)
완성!! API 테스트를 해봐도 정상적으로 잘 나온다!!❤