Reputation: 3535
Since version 3.3
it's not longer possible to define page_size on the view, as it's moved to the paginator class. related deprecations
Our API has different page_sizes defined for different views and it feels ambiguous to add new paginator subclasses just to overwrite the page_size attribute. I cannot instantiate the paginator class in the view definition and use the __init__
method as it's instantiated here. I could overwrite this and make it a method what returns an instance instantiated with the right parameters, but as its name is not get_pagination_class
, probably it's not a good idea.
My question is what would be the cleanest way to dynamically create a paginator class with the proper page_size
attribute set?
I've seen this question, and I'd like to avoid both of its solutions.
Upvotes: 13
Views: 8700
Reputation: 23144
You can achieve something relatively clean:
pagination_class
attribute.page_size
attribute in your class.In your settings.py
add a global pagination setting:
'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
'PAGE_SIZE': default_page_size,
You can handle with this all the views that have the same page size.
For any other view/viewset:
class ACustomViewSet(mixins.ListModelMixin,
mixins.DestroyModelMixin,
viewsets.GenericViewSet):
pagination_class = PageNumberPagination
page_size = N
pagination_class.page_size = self.page_size
Or you can do this inside a method:
def list(self, request, *args, **kwargs):
self.pagination_class.page_size = self.page_size
...
Upvotes: 14
Reputation: 14252
I finally ended up with customizing it in a custom pagination. It seemed like the most neat and least hacky solution.
The custom pagination
from rest_framework import pagination
class CustomPageNumberPagination(pagination.PageNumberPagination):
"""Custom page number pagination."""
page_size = 30
max_page_size = 10000
page_size_query_param = 'page_size'
def get_page_size(self, request):
"""Get page size."""
# On certain pages, force custom/max page size.
try:
view = request.parser_context['view']
if view.action in [
'custom_page_size_view_1',
'custom_page_size_view_2',
# ...
'custom_page_size_view_n',
]:
return self.max_page_size
except:
pass
return super(CustomPageNumberPagination, self).get_page_size(request)
The view
from rest_framework.viewsets import ModelViewSet
from rest_framework.decorators import list_route
from .pagination import CustomPageNumberPagination
class MyView(ModelViewSet):
pagination_class = CustomPageNumberPagination
@list_route()
def custom_page_size_view_1(self, request):
"""Custom page size view 1"""
@list_route()
def custom_page_size_view_2(self, request):
"""Custom page size view 2"""
@list_route()
def custom_page_size_view_3(self, request):
"""Custom page size view 3"""
Upvotes: 3