mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-24 00:04:16 +03:00
Clean up pagination attributes
This commit is contained in:
parent
5aa204e94f
commit
18cc0230bf
|
@ -84,10 +84,9 @@ The following attributes control the basic view behavior.
|
||||||
|
|
||||||
The following attributes are used to control pagination when used with list views.
|
The following attributes are used to control pagination when used with list views.
|
||||||
|
|
||||||
* `paginate_by` - The size of pages to use with paginated data. If set to `None` then pagination is turned off. If unset this uses the same value as the `PAGINATE_BY` setting, which defaults to `None`.
|
* `pagination_class` - The pagination class that should be used when paginating list results. Defaults to the same value as the `DEFAULT_PAGINATION_CLASS` setting, which is `'rest_framework.pagination.PageNumberPagination'`.
|
||||||
* `paginate_by_param` - The name of a query parameter, which can be used by the client to override the default page size to use for pagination. If unset this uses the same value as the `PAGINATE_BY_PARAM` setting, which defaults to `None`.
|
|
||||||
* `pagination_serializer_class` - The pagination serializer class to use when determining the style of paginated responses. Defaults to the same value as the `DEFAULT_PAGINATION_SERIALIZER_CLASS` setting.
|
Note that usage of the `paginate_by`, `paginate_by_param` and `page_kwarg` attributes are now pending deprecation. The `pagination_serializer_class` attribute and `DEFAULT_PAGINATION_SERIALIZER_CLASS` setting have been removed completely. Pagination settings should instead be controlled by overriding a pagination class and setting any configuration attributes there. See the pagination documentation for more details.
|
||||||
* `page_kwarg` - The name of a URL kwarg or URL query parameter which can be used by the client to control which page is requested. Defaults to `'page'`.
|
|
||||||
|
|
||||||
**Filtering**:
|
**Filtering**:
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ The list views for users and code snippets could end up returning quite a lot of
|
||||||
We can change the default list style to use pagination, by modifying our `tutorial/settings.py` file slightly. Add the following setting:
|
We can change the default list style to use pagination, by modifying our `tutorial/settings.py` file slightly. Add the following setting:
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'PAGINATE_BY': 10
|
'PAGE_SIZE': 10
|
||||||
}
|
}
|
||||||
|
|
||||||
Note that settings in REST framework are all namespaced into a single dictionary setting, named 'REST_FRAMEWORK', which helps keep them well separated from your other project settings.
|
Note that settings in REST framework are all namespaced into a single dictionary setting, named 'REST_FRAMEWORK', which helps keep them well separated from your other project settings.
|
||||||
|
|
|
@ -123,7 +123,7 @@ We'd also like to set a few global settings. We'd like to turn on pagination, a
|
||||||
|
|
||||||
REST_FRAMEWORK = {
|
REST_FRAMEWORK = {
|
||||||
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',),
|
'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.IsAdminUser',),
|
||||||
'PAGINATE_BY': 10
|
'PAGE_SIZE': 10
|
||||||
}
|
}
|
||||||
|
|
||||||
Okay, we're done.
|
Okay, we're done.
|
||||||
|
|
|
@ -18,6 +18,7 @@ from rest_framework.settings import api_settings
|
||||||
from rest_framework.utils.urls import (
|
from rest_framework.utils.urls import (
|
||||||
replace_query_param, remove_query_param
|
replace_query_param, remove_query_param
|
||||||
)
|
)
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
def _positive_int(integer_string, strict=False, cutoff=None):
|
def _positive_int(integer_string, strict=False, cutoff=None):
|
||||||
|
@ -203,18 +204,18 @@ class PageNumberPagination(BasePagination):
|
||||||
"""
|
"""
|
||||||
# The default page size.
|
# The default page size.
|
||||||
# Defaults to `None`, meaning pagination is disabled.
|
# Defaults to `None`, meaning pagination is disabled.
|
||||||
paginate_by = api_settings.PAGINATE_BY
|
page_size = api_settings.PAGE_SIZE
|
||||||
|
|
||||||
# Client can control the page using this query parameter.
|
# Client can control the page using this query parameter.
|
||||||
page_query_param = 'page'
|
page_query_param = 'page'
|
||||||
|
|
||||||
# Client can control the page size using this query parameter.
|
# Client can control the page size using this query parameter.
|
||||||
# Default is 'None'. Set to eg 'page_size' to enable usage.
|
# Default is 'None'. Set to eg 'page_size' to enable usage.
|
||||||
paginate_by_param = api_settings.PAGINATE_BY_PARAM
|
page_size_query_param = None
|
||||||
|
|
||||||
# Set to an integer to limit the maximum page size the client may request.
|
# Set to an integer to limit the maximum page size the client may request.
|
||||||
# Only relevant if 'paginate_by_param' has also been set.
|
# Only relevant if 'page_size_query_param' has also been set.
|
||||||
max_paginate_by = api_settings.MAX_PAGINATE_BY
|
max_page_size = None
|
||||||
|
|
||||||
last_page_strings = ('last',)
|
last_page_strings = ('last',)
|
||||||
|
|
||||||
|
@ -228,12 +229,48 @@ class PageNumberPagination(BasePagination):
|
||||||
attributes were set there. The attributes should now be set on
|
attributes were set there. The attributes should now be set on
|
||||||
the pagination class, but the old style is still pending deprecation.
|
the pagination class, but the old style is still pending deprecation.
|
||||||
"""
|
"""
|
||||||
for attr in (
|
assert not (
|
||||||
'paginate_by', 'page_query_param',
|
getattr(view, 'pagination_serializer_class', None) or
|
||||||
'paginate_by_param', 'max_paginate_by'
|
getattr(api_settings, 'DEFAULT_PAGINATION_SERIALIZER_CLASS', None)
|
||||||
|
), (
|
||||||
|
"The pagination_serializer_class attribute and "
|
||||||
|
"DEFAULT_PAGINATION_SERIALIZER_CLASS setting have been removed as "
|
||||||
|
"part of the 3.1 pagination API improvement. See the pagination "
|
||||||
|
"documentation for details on the new API."
|
||||||
|
)
|
||||||
|
|
||||||
|
for (settings_key, attr_name) in (
|
||||||
|
('PAGINATE_BY', 'page_size'),
|
||||||
|
('PAGINATE_BY_PARAM', 'page_size_query_param'),
|
||||||
|
('MAX_PAGINATE_BY', 'max_page_size')
|
||||||
):
|
):
|
||||||
if hasattr(view, attr):
|
value = getattr(api_settings, settings_key, None)
|
||||||
setattr(self, attr, getattr(view, attr))
|
if value is not None:
|
||||||
|
setattr(self, attr_name, value)
|
||||||
|
warnings.warn(
|
||||||
|
"The `%s` settings key is pending deprecation. "
|
||||||
|
"Use the `%s` attribute on the pagination class instead." % (
|
||||||
|
settings_key, attr_name
|
||||||
|
),
|
||||||
|
PendingDeprecationWarning,
|
||||||
|
)
|
||||||
|
|
||||||
|
for (view_attr, attr_name) in (
|
||||||
|
('paginate_by', 'page_size'),
|
||||||
|
('page_query_param', 'page_query_param'),
|
||||||
|
('paginate_by_param', 'page_size_query_param'),
|
||||||
|
('max_paginate_by', 'max_page_size')
|
||||||
|
):
|
||||||
|
value = getattr(view, view_attr, None)
|
||||||
|
if value is not None:
|
||||||
|
setattr(self, attr_name, value)
|
||||||
|
warnings.warn(
|
||||||
|
"The `%s` view attribute is pending deprecation. "
|
||||||
|
"Use the `%s` attribute on the pagination class instead." % (
|
||||||
|
view_attr, attr_name
|
||||||
|
),
|
||||||
|
PendingDeprecationWarning,
|
||||||
|
)
|
||||||
|
|
||||||
def paginate_queryset(self, queryset, request, view=None):
|
def paginate_queryset(self, queryset, request, view=None):
|
||||||
"""
|
"""
|
||||||
|
@ -264,7 +301,7 @@ class PageNumberPagination(BasePagination):
|
||||||
self.display_page_controls = True
|
self.display_page_controls = True
|
||||||
|
|
||||||
self.request = request
|
self.request = request
|
||||||
return self.page
|
return list(self.page)
|
||||||
|
|
||||||
def get_paginated_response(self, data):
|
def get_paginated_response(self, data):
|
||||||
return Response(OrderedDict([
|
return Response(OrderedDict([
|
||||||
|
@ -275,17 +312,17 @@ class PageNumberPagination(BasePagination):
|
||||||
]))
|
]))
|
||||||
|
|
||||||
def get_page_size(self, request):
|
def get_page_size(self, request):
|
||||||
if self.paginate_by_param:
|
if self.page_size_query_param:
|
||||||
try:
|
try:
|
||||||
return _positive_int(
|
return _positive_int(
|
||||||
request.query_params[self.paginate_by_param],
|
request.query_params[self.page_size_query_param],
|
||||||
strict=True,
|
strict=True,
|
||||||
cutoff=self.max_paginate_by
|
cutoff=self.max_page_size
|
||||||
)
|
)
|
||||||
except (KeyError, ValueError):
|
except (KeyError, ValueError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return self.paginate_by
|
return self.page_size
|
||||||
|
|
||||||
def get_next_link(self):
|
def get_next_link(self):
|
||||||
if not self.page.has_next():
|
if not self.page.has_next():
|
||||||
|
@ -336,7 +373,7 @@ class LimitOffsetPagination(BasePagination):
|
||||||
http://api.example.org/accounts/?limit=100
|
http://api.example.org/accounts/?limit=100
|
||||||
http://api.example.org/accounts/?offset=400&limit=100
|
http://api.example.org/accounts/?offset=400&limit=100
|
||||||
"""
|
"""
|
||||||
default_limit = api_settings.PAGINATE_BY
|
default_limit = api_settings.PAGE_SIZE
|
||||||
limit_query_param = 'limit'
|
limit_query_param = 'limit'
|
||||||
offset_query_param = 'offset'
|
offset_query_param = 'offset'
|
||||||
max_limit = None
|
max_limit = None
|
||||||
|
@ -349,7 +386,7 @@ class LimitOffsetPagination(BasePagination):
|
||||||
self.request = request
|
self.request = request
|
||||||
if self.count > self.limit and self.template is not None:
|
if self.count > self.limit and self.template is not None:
|
||||||
self.display_page_controls = True
|
self.display_page_controls = True
|
||||||
return queryset[self.offset:self.offset + self.limit]
|
return list(queryset[self.offset:self.offset + self.limit])
|
||||||
|
|
||||||
def get_paginated_response(self, data):
|
def get_paginated_response(self, data):
|
||||||
return Response(OrderedDict([
|
return Response(OrderedDict([
|
||||||
|
@ -440,7 +477,7 @@ class CursorPagination(BasePagination):
|
||||||
# Consider a max offset cap.
|
# Consider a max offset cap.
|
||||||
# Tidy up the `get_ordering` API (eg remove queryset from it)
|
# Tidy up the `get_ordering` API (eg remove queryset from it)
|
||||||
cursor_query_param = 'cursor'
|
cursor_query_param = 'cursor'
|
||||||
page_size = api_settings.PAGINATE_BY
|
page_size = api_settings.PAGE_SIZE
|
||||||
invalid_cursor_message = _('Invalid cursor')
|
invalid_cursor_message = _('Invalid cursor')
|
||||||
ordering = None
|
ordering = None
|
||||||
template = 'rest_framework/pagination/previous_and_next.html'
|
template = 'rest_framework/pagination/previous_and_next.html'
|
||||||
|
@ -484,7 +521,7 @@ class CursorPagination(BasePagination):
|
||||||
# We also always fetch an extra item in order to determine if there is a
|
# We also always fetch an extra item in order to determine if there is a
|
||||||
# page following on from this one.
|
# page following on from this one.
|
||||||
results = list(queryset[offset:offset + self.page_size + 1])
|
results = list(queryset[offset:offset + self.page_size + 1])
|
||||||
self.page = results[:self.page_size]
|
self.page = list(results[:self.page_size])
|
||||||
|
|
||||||
# Determine the position of the final item following the page.
|
# Determine the position of the final item following the page.
|
||||||
if len(results) > len(self.page):
|
if len(results) > len(self.page):
|
||||||
|
|
|
@ -61,9 +61,7 @@ DEFAULTS = {
|
||||||
'NUM_PROXIES': None,
|
'NUM_PROXIES': None,
|
||||||
|
|
||||||
# Pagination
|
# Pagination
|
||||||
'PAGINATE_BY': None,
|
'PAGE_SIZE': None,
|
||||||
'PAGINATE_BY_PARAM': None,
|
|
||||||
'MAX_PAGINATE_BY': None,
|
|
||||||
|
|
||||||
# Filtering
|
# Filtering
|
||||||
'SEARCH_PARAM': 'search',
|
'SEARCH_PARAM': 'search',
|
||||||
|
@ -117,7 +115,12 @@ DEFAULTS = {
|
||||||
'UNICODE_JSON': True,
|
'UNICODE_JSON': True,
|
||||||
'COMPACT_JSON': True,
|
'COMPACT_JSON': True,
|
||||||
'COERCE_DECIMAL_TO_STRING': True,
|
'COERCE_DECIMAL_TO_STRING': True,
|
||||||
'UPLOADED_FILES_USE_URL': True
|
'UPLOADED_FILES_USE_URL': True,
|
||||||
|
|
||||||
|
# Pending deprecation:
|
||||||
|
'PAGINATE_BY': None,
|
||||||
|
'PAGINATE_BY_PARAM': None,
|
||||||
|
'MAX_PAGINATE_BY': None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,9 @@ class TestPaginationIntegration:
|
||||||
return [item for item in queryset if item % 2 == 0]
|
return [item for item in queryset if item % 2 == 0]
|
||||||
|
|
||||||
class BasicPagination(pagination.PageNumberPagination):
|
class BasicPagination(pagination.PageNumberPagination):
|
||||||
paginate_by = 5
|
page_size = 5
|
||||||
paginate_by_param = 'page_size'
|
page_size_query_param = 'page_size'
|
||||||
max_paginate_by = 20
|
max_page_size = 20
|
||||||
|
|
||||||
self.view = generics.ListAPIView.as_view(
|
self.view = generics.ListAPIView.as_view(
|
||||||
serializer_class=PassThroughSerializer,
|
serializer_class=PassThroughSerializer,
|
||||||
|
@ -185,7 +185,7 @@ class TestPageNumberPagination:
|
||||||
|
|
||||||
def setup(self):
|
def setup(self):
|
||||||
class ExamplePagination(pagination.PageNumberPagination):
|
class ExamplePagination(pagination.PageNumberPagination):
|
||||||
paginate_by = 5
|
page_size = 5
|
||||||
self.pagination = ExamplePagination()
|
self.pagination = ExamplePagination()
|
||||||
self.queryset = range(1, 101)
|
self.queryset = range(1, 101)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user