Skip to content Skip to sidebar Skip to footer

Django Rest Framework Global Pagination Parameters Not Working For Modelviewset

The DRF docs state that: Pagination is only performed automatically if you're using the generic views or viewsets. But I'm using a ModelViewSet which inherits from ViewSet, so I

Solution 1:

It is true that pagination doesn't work by default on a ModelViewSet despite inheriting from GenericViewSet and the ListMixin. You need to add it manually:

I have composed a Q&A style example which attends that problem and have tested it on a ModelViewSet class.

I will summarize it a bit:

  1. Create a custom mixin to utilize the pagination_class:

    classMyPaginationMixin(object):
        @propertydefpaginator(self):
            """
            The paginator instance associated with the view, or `None`.
            """ifnothasattr(self, '_paginator'):
                 if self.pagination_classisNone:
                     self._paginator = Noneelse:
                     self._paginator = self.pagination_class()
             return self._paginator
    
         defpaginate_queryset(self, queryset):
             """
             Return a single page of results, or `None` if pagination 
             is disabled.
             """if self.paginator isNone:
                 returnNonereturn self.paginator.paginate_queryset(
                 queryset, self.request, view=self)
    
         defget_paginated_response(self, data):
             """
             Return a paginated style `Response` object for the given 
             output data.
             """assert self.paginator isnotNonereturn self.paginator.get_paginated_response(data)
    
  2. Make your viewset extend that mixin and override the list() method of the ModelViewSet:

    classMyViewset(MyPaginationMixin, viewsets.ModelViewSet):
        # since you are setting pagination on the settings, use this:
        pagination_class = settings.DEFAULT_PAGINATION_CLASS
    
        deflist(self, request, *args, **kwargs):
            response = dict(
                super(MyViewSet, self).list(self, *args, **kwargs).data)
    
            page = self.paginate_queryset(response['results'])
            if page isnotNone:
                serializer = self.serializer_class(page, many=True)
                return self.get_paginated_response(serializer.data)
            else:
                # Something went wrong here...

You need to calibrate this solution to your needs of course, but this will add pagination to a ModelViewSet.


For the subquestion, @Linovia 's comment is correct, PAGINATE_BY is deprecated and PAGE_SIZE is the current setting for the response page size.

Solution 2:

It should work. If it doesn't and you don't have typo, look at the server logs and you may find something telling you that pagination without order will not work:

xxxx/django/core/paginator.py:112: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: ....

In order to fix that make sure you specify an ordering in the model's Meta or set an order_by within ModelViewSet's queryset.

Post a Comment for "Django Rest Framework Global Pagination Parameters Not Working For Modelviewset"