[Fixed]-Django rest framework: how to turn off/on pagination in ModelViewSet

18👍

One option would be to dynamically disable pagination on the view by setting a no_page query parameter:

def paginate_queryset(self, queryset, request, view=None):
    if 'no_page' in request.query_params:
        return None

    return super().paginate_queryset(queryset, request, view)

8👍

This solution is working for me

DRF Version: 3.11.0

Django Version: 2.2.7

By default pagination is working but when I will pass the query param ‘no_page’ then pagination will be disabled:
like: http://localhost:8000/api/city/?no_page

class CityListView(generics.ListCreateAPIView):
    serializer_class = serializers.CitySerializer
    def paginate_queryset(self, queryset, view=None):
        if 'no_page' in self.request.query_params:
            return None
        else:
            return self.paginator.paginate_queryset(queryset, self.request, view=self)

7👍

if you just want to turn on or off pagination by client dynamically,you can custom Pagination class as:

class Pagination(PageNumberPagination):
    page_size_query_param = 'page_size'
    max_page_size = 100

    def get_page_size(self, request):
        if self.page_size_query_param:
            page_size = min(int(request.query_params.get(self.page_size_query_param, self.page_size)),
                        self.max_page_size)
            if page_size > 0:
                return page_size
            elif page_size == 0:
                return None
            else:
                pass
        return self.page_size

use this class as your pagination_class and you can turn off pagination by request url “http://www.example.com/some_object/?page_size=0“, ?page_size=0 will disable pagination.
if you just want disable pagination when request format is CVS,you can try what danilke said.

👤Ykh

3👍

simply you can use pagination_class = None inside your class:

class MyClassBasedView(ModelViewSet):
    pagination_class = None

2👍

It doesn’t work anymore (at least not in latest version), you should do something like

 def paginate_queryset(self, queryset, request, view=None):
     if 'page' not in request.query_params:
            return queryset
     return super().paginate_queryset(queryset)

and call the function with self.paginate_queryset(queryset, request) when inside the list method

👤Maxpnl

0👍

Solution is:

class PaginatedCSVRenderer (CSVRenderer):
    results_field = 'results'

    def render(self, data, *args, **kwargs):
        if not isinstance(data, list):
            data = data.get(self.results_field, [])
        return super(PaginatedCSVRenderer, self).render(data, *args, **kwargs)

and than:

class ObjectViewSet(BaseViewSet, viewsets.ModelViewSet):

    queryset = Object.objects.none()
    serializer_class = ObjectSerializer
    renderer_classes =  (JSONRenderer, PaginatedCSVRenderer)

and delete from settings:

   'PAGE_SIZE': 10,

0👍

Perhaps a more future-proof approach – open up my_venv/lib/python3.8/site-packages/rest_framework/generics.py – replacing my_venv and your Python version, scroll to around line 165 and copy the method signature for paginate_queryset. Also check what it returns if self.paginator is None – that is what to return if you want to disable pagination.

On DRF 3.11 the parent method signature is paginate_queryset(self, queryset), and if self.paginator is None it returns None, so I used:

def paginate_queryset(self, queryset):
    if 'page_id' in self.request.query_params:
        return None
    return super().paginate_queryset(queryset)

I haven’t tested it but I guess the answer to the OP question is (assuming a fairly default DRF config):

if ('format' in self.request.query_params and 
        self.request.query_params['format'] == 'csv'):
👤Chris

0👍

My solution:

  • default but customizable page_size
  • only applies pagination if page param is provided
  • otherwise returns the whole list
# paginators.py

class CustomPagination(PageNumberPagination):
    page_size = 10  # default
    page_size_query_param = "page_size"  # param to set a custom page_size
    max_page_size = 50

    def paginate_queryset(self, queryset, request, view=None):
        # if the page param is not provided, do not apply pagination
        if request.query_params.get(self.page_query_param, None) is None:
            return None

        return super().paginate_queryset(queryset, request, view)

Usage:

#views.py

from .paginators import CustomPagination

class ObjectViewSet(BaseViewSet, viewsets.ModelViewSet):
    queryset = Object.objects.none()
    serializer_class = ObjectSerializer
    pagination_class = CustomPagination

Tested and working with Django 4.2 and DRF 3.14.

Leave a comment