I am using APIView
for get and post items.
I wanted to implement pagination for my API using Django Rest Framework, but it is not working.
I want
extend GenericAPIView
instead of APIView
and define pagination_class
in GenericAPIView
You could make your life a lot easier and just use a ListView. By overriding render_to_response you can make it output json instead of HTML. It does all the pagination for you.
from django.core import serializers
from django.views.generic import ListView
class MyListView(JSONResponseMixin, ListView):
model = models.BaseItem
paginate_by = 10
def render_to_response(self, context):
return JsonResponse(
serializers.serialize("json", context),
**response_kwargs
)
paginator = None worked for me
> class NotesViewSet(viewsets.ModelViewSet):
> queryset = Notes.objects.all()
> serializer_class = NotesWriteSerializer
> paginator = None
Non generic views and viewsets do not have pagination by default as stated in the django rest framework documentation:
Pagination is only performed automatically if you're using the generic views or viewsets. If you're using a regular
APIView
, you'll need to call into the pagination API yourself to ensure you return a paginated response. See the source code for themixins.ListModelMixin
andgenerics.GenericAPIView
classes for an example.
I have composed a full example on enabling pagination on non generic views with code on how to achieve this:
class ItemsAPIView(APIView):
permission_classes = (permissions.IsAuthenticated,)
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
serializer_class = MyNewUnifiedSerializerClass
def get(self, request):
user_items = BaseItem.objects.filter(
owner=request.user
).distinct()
page = self.paginate_queryset(user_items)
if page is not None:
serializer = self.serializer_class(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(user_items, many=True)
return Response(serializer.data)
# 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)
For more details have a look at the example link provided.