Skip to content

Commit 8b19ec1

Browse files
pushpit kambojpushpit kamboj
authored andcommitted
[feature] Added OpenWispPagination class with suitable default values
1 parent 9f2ab62 commit 8b19ec1

2 files changed

Lines changed: 146 additions & 0 deletions

File tree

docs/developer/other-utilities.rst

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,99 @@ Every openwisp module which has an API should use this class to configure
8383
its own default settings, which will be merged with the settings of the
8484
other modules.
8585

86+
``openwisp_utils.api.pagination.OpenWispPagination``
87+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
88+
89+
A reusable pagination class for DRF views that provides consistent
90+
pagination behavior across OpenWISP modules with sensible defaults and
91+
flexible configuration.
92+
93+
**Default Behavior:**
94+
95+
- 10 items per page
96+
- Clients can request custom page sizes via ``?page_size=N`` query
97+
parameter
98+
- Maximum 100 items per page to prevent performance issues
99+
- Standard page navigation via ``?page=N``
100+
101+
**Configuration via Django Settings:**
102+
103+
The pagination class reads settings dynamically, making it compatible with
104+
Django's ``override_settings`` decorator in tests. The following settings
105+
can be used to customize the default pagination behavior:
106+
107+
- ``OPENWISP_PAGINATION_PAGE_SIZE`` (default: ``10``): Default number of
108+
items per page
109+
- ``OPENWISP_PAGINATION_MAX_PAGE_SIZE`` (default: ``100``): Maximum
110+
allowed page size
111+
- ``OPENWISP_PAGINATION_PAGE_SIZE_QUERY_PARAM`` (default:
112+
``"page_size"``): Query parameter name for page size
113+
114+
**Usage in Views:**
115+
116+
.. code-block:: python
117+
118+
from openwisp_utils.api.pagination import OpenWispPagination
119+
from rest_framework.viewsets import ModelViewSet
120+
121+
122+
class DeviceViewSet(ModelViewSet):
123+
queryset = Device.objects.all()
124+
serializer_class = DeviceSerializer
125+
pagination_class = OpenWispPagination
126+
127+
**Custom Configuration via Subclassing:**
128+
129+
For view-specific pagination requirements, you can subclass
130+
``OpenWispPagination`` and override the properties:
131+
132+
.. code-block:: python
133+
134+
from openwisp_utils.api.pagination import OpenWispPagination
135+
136+
137+
class LargePagination(OpenWispPagination):
138+
@property
139+
def page_size(self):
140+
return 50
141+
142+
@property
143+
def max_page_size(self):
144+
return 500
145+
146+
147+
class ReportViewSet(ModelViewSet):
148+
queryset = Report.objects.all()
149+
serializer_class = ReportSerializer
150+
pagination_class = LargePagination
151+
152+
**Global Configuration:**
153+
154+
To use ``OpenWispPagination`` as the default pagination class for all DRF
155+
views in your project, add it to ``REST_FRAMEWORK`` settings:
156+
157+
.. code-block:: python
158+
159+
REST_FRAMEWORK = {
160+
"DEFAULT_PAGINATION_CLASS": "openwisp_utils.api.pagination.OpenWispPagination",
161+
}
162+
163+
**API Request Examples:**
164+
165+
.. code-block:: bash
166+
167+
# Returns first 10 items (default page size)
168+
GET /api/devices/
169+
170+
# Returns items 11-20 (second page)
171+
GET /api/devices/?page=2
172+
173+
# Returns first 25 items (custom page size)
174+
GET /api/devices/?page_size=25
175+
176+
# Returns items 26-50 with custom page size
177+
GET /api/devices/?page=2&page_size=25
178+
86179
Storage Utilities
87180
-----------------
88181

openwisp_utils/api/pagination.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
from django.conf import settings
2+
from django.core.exceptions import ImproperlyConfigured
3+
4+
try:
5+
from rest_framework.pagination import PageNumberPagination
6+
except ImportError: # pragma: nocover
7+
raise ImproperlyConfigured(
8+
"Django REST Framework is required to use "
9+
"this feature but it is not installed"
10+
)
11+
12+
13+
class OpenWispPagination(PageNumberPagination):
14+
"""Reusable pagination class with sensible defaults.
15+
16+
Configurable via Django settings: - OPENWISP_PAGINATION_PAGE_SIZE
17+
(default: 10) - OPENWISP_PAGINATION_MAX_PAGE_SIZE (default: 100) -
18+
OPENWISP_PAGINATION_PAGE_SIZE_QUERY_PARAM (default: 'page_size')
19+
"""
20+
21+
@property
22+
def page_size(self):
23+
"""Return the page size from settings or default."""
24+
if hasattr(self, "_page_size"):
25+
return self._page_size
26+
return getattr(settings, "OPENWISP_PAGINATION_PAGE_SIZE", 10)
27+
28+
@page_size.setter
29+
def page_size(self, value):
30+
self._page_size = value
31+
32+
@property
33+
def max_page_size(self):
34+
if hasattr(self, "_max_page_size"):
35+
return self._max_page_size
36+
return getattr(settings, "OPENWISP_PAGINATION_MAX_PAGE_SIZE", 100)
37+
38+
@max_page_size.setter
39+
def max_page_size(self, value):
40+
"""Allow setting max_page_size."""
41+
self._max_page_size = value
42+
43+
@property
44+
def page_size_query_param(self):
45+
if hasattr(self, "_page_size_query_param"):
46+
return self._page_size_query_param
47+
return getattr(
48+
settings, "OPENWISP_PAGINATION_PAGE_SIZE_QUERY_PARAM", "page_size"
49+
)
50+
51+
@page_size_query_param.setter
52+
def page_size_query_param(self, value):
53+
self._page_size_query_param = value

0 commit comments

Comments
 (0)