Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django rest framework override page_size in ViewSet

I am having problem with django rest framework pagination. I have set pagination in settings like -

'DEFAULT_PAGINATION_CLASS':'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': 1

Below is my viewset.

class HobbyCategoryViewSet(viewsets.ModelViewSet):    
    serializer_class = HobbyCategorySerializer
    queryset = UserHobbyCategory.objects.all()

I want to set different page size for this viewset. I have tried setting page_size and Paginate_by class variables but list is paginated according to PAGE_SIZE defined in settings. Any idea where I am wrong ?

like image 597
Mangesh Avatar asked Feb 16 '16 12:02

Mangesh


People also ask

Should I use APIView or ViewSet?

APIView allow us to define functions that match standard HTTP methods like GET, POST, PUT, PATCH, etc. Viewsets allow us to define functions that match to common API object actions like : LIST, CREATE, RETRIEVE, UPDATE, etc.

Can we do pagination for data in REST framework?

REST framework includes support for customizable pagination styles. This allows you to modify how large result sets are split into individual pages of data.

What is ViewSet in Django REST framework?

A ViewSet class is simply a type of class-based View, that does not provide any method handlers such as . get() or . post() , and instead provides actions such as . list() and . create() .

How do I Paginate in Django REST framework?

To create a custom pagination class, first create a paginations.py file in your app folder and create a class that inherits from an existing DRF paginator. The parameters given in this custom paginator class will enable you to provide a page_size query parameter to determine the size of each page.


4 Answers

I fixed this by creating custom pagination class. and setting desired pagesize in class. I have used this class as pagination_class in my viewset.

from rest_framework import pagination

class ExamplePagination(pagination.PageNumberPagination):       
       page_size = 2

class HobbyCategoryViewSet(viewsets.ModelViewSet):    
    serializer_class = HobbyCategorySerializer
    queryset = UserHobbyCategory.objects.all()
    pagination_class=ExamplePagination

I am not sure if there is any easier way for this. this one worked for me. But I think its not good to create new class just to change page_size.

Edit - simple solution is set it like

pagination.PageNumberPagination.page_size = 100 

in ViewSet.

class HobbyCategoryViewSet(viewsets.ModelViewSet):    
    serializer_class = HobbyCategorySerializer
    queryset = UserHobbyCategory.objects.all()
    pagination.PageNumberPagination.page_size = 100 
like image 180
Mangesh Avatar answered Oct 07 '22 10:10

Mangesh


Use page size query params to provide page size dynamically..

from rest_framework.pagination import PageNumberPagination

class StandardResultsSetPagination(PageNumberPagination):
    page_size_query_param = 'limit'

Set Default pagination class in settings

REST_FRAMEWORK = {'DEFAULT_PAGINATION_CLASS': 'StandardResultsSetPagination',}

Now in your URL provide limit as a GET parameter..

http://example.com/list/?limit=100 or 25

like image 38
Naresh Avatar answered Oct 07 '22 08:10

Naresh


In the case that you want to set a default pagination value, including a max and a param, here is what you do.

1) Create a drf_defaults.py (or any name you choose). I placed it in same dir as settings.py:

"""
Django rest framework default pagination
"""
from rest_framework.pagination import PageNumberPagination


class DefaultResultsSetPagination(PageNumberPagination):
    page_size = 50
    page_size_query_param = 'page_size'
    max_page_size = 100000

2) In your settings.py, update REST_FRAMEWORK dict, adding the following:

'DEFAULT_PAGINATION_CLASS': 'drf_defaults.DefaultResultsSetPagination',

In the end my REST_FRAMEWORK settings dict looks like:

# http://www.django-rest-framework.org/api-guide/settings/
REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        # 'rest_framework.permissions.AllowAny',  # Use to disable api auth
        # 'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
        'permissions.IsAuthenticatedWriteOrReadOnly',
    ],
    'DEFAULT_AUTHENTICATION_CLASSES': [
        # 'oauth2_provider.contrib.rest_framework.OAuth2Authentication',  # Own oauth server
        'client_authentication.ApiTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ],
    # Enable DRF pagination
    # 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
    'DEFAULT_PAGINATION_CLASS': 'drf_defaults.DefaultResultsSetPagination',
    'PAGE_SIZE': 50,
    'DEFAULT_RENDERER_CLASSES': (
        # 'rest_framework.renderers.JSONRenderer',  # Swapping out the original renderer
        'lib.drf_renderer.UJSONRenderer',
        'rest_framework.renderers.BrowsableAPIRenderer',
    ),
    'DEFAULT_PARSER_CLASSES': (
        # 'rest_framework.parsers.JSONParser',  # Swapping out the original parser
        'lib.drf_parser.UJSONParser',
        'rest_framework.parsers.FormParser',
        'rest_framework.parsers.MultiPartParser'
    ),
    'DEFAULT_FILTER_BACKENDS': (
        'django_filters.rest_framework.DjangoFilterBackend',
    )
}

Your settings will of course vary! Cheers!

like image 4
radtek Avatar answered Oct 07 '22 09:10

radtek


In case you are trying to change the "page size" of the LimitOffsetPagination class, you have to override the default_limit variable instead of page_size:

from rest_framework import paginationclass 


CustomLimitOffsetPagination(pagination.LimitOffsetPagination):
    default_limit = 5
like image 1
oneschilling Avatar answered Oct 07 '22 08:10

oneschilling