Django Rest Framework - APIView Pagination
I have a very simple APIView
, but I don't know how to setup pagination here.
In this scenario I select an Event
with given pk
, then I get all the NewsItems
assigned to this Event
.
pagination_class = LimitOffsetPagination
works OK when I define queryset at the beginning in ListCreateAPIView
, for ex. queryset = Event.objects.all()
but not with custom get
:
class EventNewsItems(APIView):
pagination_class = LimitOffsetPagination
def get(self, request, pk, format=None):
#user = request.user
event = Event.objects.get(pk=pk)
news = event.get_news_items().all()
serializer = NewsItemSerializer(news, many=True, context={'request':request})
response = Response(serializer.data, status=status.HTTP_200_OK)
return response
Solved:
def get(self, request, pk, format=None):
#user = request.user
event = Event.objects.get(pk=pk)
news = event.get_news_items().all()
paginator = LimitOffsetPagination()
result_page = paginator.paginate_queryset(news, request)
serializer = NewsItemSerializer(result_page, many=True, context={'request':request})
response = Response(serializer.data, status=status.HTTP_200_OK)
return response
Another option would be inheriting from the pagination class, with fewer changes on the view class:
from rest_framework.pagination import LimitOffsetPagination
class EventNewsItems(APIView, LimitOffsetPagination):
def get(self, request, pk, format=None):
event = Event.objects.get(pk=pk)
news = event.get_news_items().all()
results = self.paginate_queryset(news, request, view=self)
serializer = NewsItemSerializer(results, many=True)
return self.get_paginated_response(serializer.data)
I have created a Q&A style example on this subject.
As a sort summary:
By utilizing the Django Rest Frameworks source code and how they handle pagination, we create the same methods inside our view class and we use them, in the same way your solution uses the default methods:
Taken from the above mentioned doc:
from rest_framework.settings import api_settings from rest_framework.views import APIView class MyView(APIView): queryset = OurModel.objects.all() serializer_class = OurModelSerializer pagination_class = api_settings.DEFAULT_PAGINATION_CLASS # cool trick right? :) # We need to override get method to achieve pagination def get(self, request): ... page = self.paginate_queryset(self.queryset) if page is not None: serializer = self.serializer_class(page, many=True) return self.get_paginated_response(serializer.data) ... Do other stuff needed (out of scope of pagination) # Now add the pagination handlers taken from # django-rest-framework/rest_framework/generics.py @property def paginator(self): """ The paginator instance associated with the view, or `None`. """ if not hasattr(self, '_paginator'): if self.pagination_class is None: self._paginator = None else: self._paginator = self.pagination_class() return self._paginator def paginate_queryset(self, queryset): """ Return a single page of results, or `None` if pagination is disabled. """ if self.paginator is None: return None return self.paginator.paginate_queryset(queryset, self.request, view=self) def get_paginated_response(self, data): """ Return a paginated style `Response` object for the given output data. """ assert self.paginator is not None return self.paginator.get_paginated_response(data)