Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django Rest Framework: turn on pagination on a ViewSet (like ModelViewSet pagination)

I have a ViewSet like this one to list users' data:

class Foo(viewsets.ViewSet):      def list(self, request):         queryset = User.objects.all()         serializer = UserSerializer(queryset, many=True)         return Response(serializer.data) 

I want to turn on pagination like the default pagination for ModelViewSet:

{     "count": 55,     "next": "http://myUrl/?page=2",     "previous": null,     "results": [{...},{...},...,{...}] } 

The official doc says:

Pagination is only performed automatically if you're using the generic views or viewsets

...but my resultset is not paginated at all. How can I paginate it?

like image 880
floatingpurr Avatar asked Aug 03 '15 11:08

floatingpurr


People also ask

How Pagination works in django REST framework?

Django provides a few classes that help you manage paginated data – that is, data that's split across several pages, with “Previous/Next” links. REST framework includes support for customizable pagination styles. This allows you to modify how large result sets are split into individual pages of data.

How do you implement Pagination in DRF?

To enable this pagination style globally, you can set rest_framework. pagination. PageNumberPagination class to DEFAULT_PAGINATION_CLASS and also set the PAGE_SIZE as desired. You can open the settings.py file and add the below configuration settings.

Should either include a Serializer_class attribute or override the?

serializer_class - The serializer class that should be used for validating and deserializing input, and for serializing output. Typically, you must either set this attribute, or override the get_serializer_class() method.


2 Answers

For those using DRF 3.1 or higher, they are changing the default way pagination is handled. See http://www.django-rest-framework.org/topics/3.1-announcement/ for details.

Now if you want to enable pagination for a ModelViewSet you can either do it globally by setting in your settings.py file:

REST_FRAMEWORK = {     'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',     'PAGE_SIZE': 100 } 

Or if you just want it for one ModelViewSet you can manually set the pagination_class for just that viewset.

from rest_framework.pagination import PageNumberPagination  class StandardResultsSetPagination(PageNumberPagination):     page_size = 100     page_size_query_param = 'page_size'     max_page_size = 1000  class FooViewSet(viewsets.ModelViewSet):     pagination_class = StandardResultsSetPagination 

This also allows you to tweak the way the pagination is handled for just that viewset.

DRF 3.1 also has introduced new types of default pagination schemes that you can use such as LimitOffset and Cursor.

like image 106
jeffjv Avatar answered Sep 21 '22 01:09

jeffjv


Pagination is only performed automatically if you're using the generic views or viewsets

The first roadblock is translating the docs to english. What they intended to convey is that you desire a generic viewset. The generic viewsets extend from generic ApiViews which have extra class methods for paginating querysets and responses.

Additionally, you're providing your own list method, but the default pagination process is actually handled by the mixin:

class ListModelMixin(object):     """     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) 

The easy solution, use the framework code:

class Foo(mixins.ListModelMixin, viewsets.GenericViewSet):     queryset = User.objects.all()     serializer = UserSerializer 

The more complex solution would be if you need a custom list method, then you should write it as you see fit but in the style of the above mixin code snippet.

like image 41
Mark Galloway Avatar answered Sep 22 '22 01:09

Mark Galloway