44๐
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
25๐
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
- [Django]-Accessing "Media" files in Django
- [Django]-Trying to parse `request.body` from POST in Django
- [Django]-Django: How to access original (unmodified) instance in post_save signal
5๐
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!
- [Django]-Django: reverse accessors for foreign keys clashing
- [Django]-How to log all sql queries in Django?
- [Django]-Python + Django page redirect
1๐
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
- [Django]-Coverage.py warning: No data was collected. (no-data-collected)
- [Django]-How to use Python type hints with Django QuerySet?
- [Django]-How to make a PATCH request using DJANGO REST framework
0๐
Simplest Solution
For LimitOffsetPagination :
viewsets.ModelViewSet.pagination_class.default_limit = 10 #Page limit
For PageNumberPagination:
viewsets.ModelViewSet.pagination_class.page_size = 10 #Page limit
For CursorPagination:
viewsets.ModelViewSet.pagination_class.page_size = 10 #Page limit
Full Code:
class HobbyCategoryViewSet(viewsets.ModelViewSet):
serializer_class = HobbyCategorySerializer
queryset = UserHobbyCategory.objects.all()
viewsets.ModelViewSet.pagination_class.default_limit = 10 #Page limit
Make sure you have DEFAULT_PAGINATION_CLASS in your settings.
- [Django]-Tailwindcss: fixed/sticky footer on the bottom
- [Django]-Django REST Framework image upload
- [Django]-Redirect / return to same (previous) page in Django?
0๐
use this
from rest_framework.pagination import PageNumberPagination
class StandardResultsSetPagination(PageNumberPagination):
page_size = 100
page_size_query_param = 'page_size'
apply the style globally, using the DEFAULT_PAGINATION_CLASS settings key
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'your_app*.your_class_file*.StandardResultsSetPagination',
}
example of usage
http://127.0.0.1:8000/produits/api/?page_size=3&page=1
- [Django]-Django โ limiting query results
- [Django]-Get name of primary field of Django model
- [Django]-H14 error in heroku โ "no web processes running"
0๐
Anyone experiencing this issue should read this article: http://masnun.rocks/2017/03/20/django-admin-expensive-count-all-queries/
To simplify, there are 2 triggers of the expensive COUNT(*)
behavior
- the paginator. You need to override it in your ModelAdmin class. Create a class like the one below (for Postgres) or
class LargeTablePaginator(Paginator):
def _get_count(self):
if getattr(self, '_count', None) is not None:
return self._count
query = self.object_list.query
if not query.where:
with connections['default'].cursor() as cursor:
cursor.execute("SELECT reltuples FROM pg_class WHERE relname = %s",
[query.model._meta.db_table])
self._count = int(cursor.fetchone()[0])
else:
self._count = super(LargeTablePaginator, self)._get_count()
return self._count
count = property(_get_count)
then override it in your ModelAdmin with:
paginator = LargeTablePaginator
-
In Django >1.8, you need to also add:
show_full_result_count = False
to your ModelAdmin class.
Performing these 2 steps was the only way I was able to eliminate all count(*)
queries.
- [Django]-PermissionError: [Errno 13] Permission denied: '/manage.py'
- [Django]-Accessing "Media" files in Django
- [Django]-How can I embed django csrf token straight into HTML?
0๐
I jumped into a similar problem and could not find a proper answer.
Most of the answers change the default page_size and it affects other API views too.
Here I post how I handled it at last.
Define custom pagination and a function returning pagination class.
# pagination.py
from rest_framework import pagination
class CustomPagination(pagination.PageNumberPagination):
def get_paginated_response(self, data):
response = super(CustomPagination, self).get_paginated_response(data)
response.data['total_pages'] = self.page.paginator.num_pages
return response
def CustomPaginationWithSize(_page_size = 10):
class CustomPaginationWithSize(pagination.PageNumberPagination):
page_size = _page_size
def get_paginated_response(self, data):
response = super(CustomPaginationWithSize, self).get_paginated_response(data)
response.data['total_pages'] = self.page.paginator.num_pages
return response
return CustomPaginationWithSize
In your settings.py, set the default pagination with the above custom pagination class.
REST_FRAMEWORK = {
# ...
'DEFAULT_PAGINATION_CLASS': 'api.pagination.CustomPagination',
'PAGE_SIZE': 20,
# ...
}
Now PageNumberPaginationWithCount
is applied for all Views with page_size=20
as long as you do not specify pagination_class=None
in the View class explicitly.
Finally, for Views that need custom page size, use the function returning custom pagination class as follows.
# sample viewset that needs custom page size 5
class PersonListView(generics.ListAPIView):
permission_classes = (permissions.IsAuthenticated, )
serializer_class = PersonSerializer
pagination_class = CustomPaginationWithSize(5)
queryset = Person.objects.all()
This does not affect other views and resolves the OPโs problem.
- [Django]-Django Many-to-Many (m2m) Relation to same model
- [Django]-Pre-populate an inline FormSet?
- [Django]-InterfaceError (0, '')
0๐
settings.py
REST_FRAMEWORK = {
#'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
#'PAGE_SIZE':10
}
these settings will affect every endpoints better to remove both settings from settings.py
views.py
from .pagination import DefaultPagination
class ProductViewSet(ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
pagination_class = DefaultPagination
pagination.py
from rest_framework.pagination import PageNumberPagination
class DefaultPagination(PageNumberPagination):
page_size = 10
- [Django]-Django's timezone.now does not show the right time
- [Django]-How do I get the object if it exists, or None if it does not exist in Django?
- [Django]-Django 2.0 โ Not a valid view function or pattern name (Customizing Auth views)
0๐
If you need use custom DRF pagination on the fly (without defining custom classes)
from rest_framework.settings import api_settings
def custom_paginator(cls=None, **kwargs):
# Creating a new class dynamically based on the given base class and additional attributes
cls = cls or api_settings.DEFAULT_PAGINATION_CLASS
new_class_name = f"Custom{cls.__name__}Paginator_{id(kwargs)}"
return type(new_class_name, (cls,), kwargs)
Usage
class YourViewSet(viewsets.ModelViewSet):
pagination_class = custom_paginator(page_size=50, max_page_size=100)
# or
@action(methods=['GET'], detail=False, pagination_class=custom_paginator(page_size=5))
def additional_list(self, request, *args, **kwargs):
...
- [Django]-Django url pattern โ string parameter
- [Django]-Accessing function as attribute in a Python class
- [Django]-Django โ No such table: main.auth_user__old