Skip to content

Commit 9d7d87f

Browse files
committed
Add additional test coverage, add extra exception handling for page numbers
1 parent 9d7e879 commit 9d7d87f

File tree

2 files changed

+103
-3
lines changed

2 files changed

+103
-3
lines changed

rest_framework_datatables/pagination.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ def get_page_size(self, request):
5656
pass
5757
return self.page_size
5858

59+
def get_page(self, request, page_size):
60+
try:
61+
start = int(get_param(request, self.page_query_param, 0))
62+
return int(start / page_size) + 1
63+
except ValueError:
64+
return None
65+
5966
def paginate_queryset(self, queryset, request, view=None):
6067
if request.accepted_renderer.format != 'datatables':
6168
self.is_datatable_request = False
@@ -87,8 +94,7 @@ def count(self):
8794
return self.value
8895

8996
paginator = CachedCountPaginator(self.count, queryset, page_size)
90-
start = int(get_param(request, self.page_query_param, 0))
91-
page_number = int(start / page_size) + 1
97+
page_number = self.get_page(request, page_size)
9298

9399
try:
94100
self.page = paginator.page(page_number)

tests/test_api.py

Lines changed: 95 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,14 @@ def post(self, request, *args, **kwargs):
2323
return self.list(request, *args, **kwargs)
2424

2525

26+
class DatatablesPageNumberPaginationCustomMax(DatatablesPageNumberPagination):
27+
max_page_size = 15
28+
29+
30+
class DatatablesLimitOffsetPaginationCustomMax(DatatablesLimitOffsetPagination):
31+
max_limit = 15
32+
33+
2634
class TestApiTestCase(TestCase):
2735
fixtures = ['test_data']
2836

@@ -82,10 +90,36 @@ def test_pagenumber_pagination_show_all(self):
8290
result = response.json()
8391
self.assertEquals((result['recordsFiltered'], result['recordsTotal'], len(result['data']), result['data'][0]['artist_name']), expected)
8492

85-
def test_pagenumber_pagination_invalid_page(self):
93+
def test_pagenumber_pagination_invalid_page1(self):
8694
response = self.client.get('/api/albums/?format=datatables&length=10&start=20&columns[0][data]=name&columns[1][data]=artist_name&draw=1')
8795
self.assertEquals(response.status_code, 404)
8896

97+
def test_pagenumber_pagination_invalid_page2(self):
98+
response = self.client.get('/api/albums/?format=datatables&length=10&start=abc&columns[0][data]=name&columns[1][data]=artist_name&draw=1')
99+
self.assertEquals(response.status_code, 404)
100+
101+
def test_pagenumber_pagination_invalid_page_size1(self):
102+
response = self.client.get('/api/albums/?format=datatables&length=abc&start=10&columns[0][data]=name&columns[1][data]=artist_name&draw=1')
103+
expected = (15, 15, 5, 'Elvis Presley')
104+
result = response.json()
105+
self.assertEquals((result['recordsFiltered'], result['recordsTotal'], len(result['data']), result['data'][0]['artist_name']), expected)
106+
107+
def test_pagenumber_pagination_invalid_page_size2(self):
108+
response = self.client.get('/api/albums/?format=datatables&length=-999&start=10&columns[0][data]=name&columns[1][data]=artist_name&draw=1')
109+
expected = (15, 15, 5, 'Elvis Presley')
110+
result = response.json()
111+
self.assertEquals((result['recordsFiltered'], result['recordsTotal'], len(result['data']), result['data'][0]['artist_name']), expected)
112+
113+
@override_settings(REST_FRAMEWORK={
114+
'DEFAULT_PAGINATION_CLASS': __name__ + '.DatatablesPageNumberPaginationCustomMax',
115+
})
116+
def test_pagenumber_pagination_invalid_max(self):
117+
AlbumViewSet.pagination_class = DatatablesPageNumberPaginationCustomMax
118+
response = self.client.get('/api/albums/?format=datatables&length=20&start=10&columns[0][data]=name&columns[1][data]=artist_name&draw=1')
119+
expected = (15, 15, 15, 'The Beatles')
120+
result = response.json()
121+
self.assertEquals((result['recordsFiltered'], result['recordsTotal'], len(result['data']), result['data'][0]['artist_name']), expected)
122+
89123
@override_settings(REST_FRAMEWORK={
90124
'DEFAULT_PAGINATION_CLASS': 'rest_framework_datatables.pagination.DatatablesLimitOffsetPagination',
91125
})
@@ -108,6 +142,66 @@ def test_limitoffset_pagination_no_length(self):
108142
result = response.json()
109143
self.assertEquals((result['recordsFiltered'], result['recordsTotal'], result['data'][0]['artist_name']), expected)
110144

145+
@override_settings(REST_FRAMEWORK={
146+
'DEFAULT_PAGINATION_CLASS': 'rest_framework_datatables.pagination.DatatablesLimitOffsetPagination',
147+
})
148+
def test_limitoffset_pagination_invalid_length1(self):
149+
AlbumViewSet.pagination_class = DatatablesLimitOffsetPagination
150+
client = APIClient()
151+
response = client.get(
152+
'/api/albums/?format=datatables&length=abc&start=10&columns[0][data]=name&columns[1][data]=artist_name&draw=1')
153+
expected = (15, 15, 'Elvis Presley')
154+
result = response.json()
155+
self.assertEquals((result['recordsFiltered'], result['recordsTotal'], result['data'][0]['artist_name']), expected)
156+
157+
@override_settings(REST_FRAMEWORK={
158+
'DEFAULT_PAGINATION_CLASS': 'rest_framework_datatables.pagination.DatatablesLimitOffsetPagination',
159+
})
160+
def test_limitoffset_pagination_invalid_length2(self):
161+
AlbumViewSet.pagination_class = DatatablesLimitOffsetPagination
162+
client = APIClient()
163+
response = client.get(
164+
'/api/albums/?format=datatables&length=-999&start=10&columns[0][data]=name&columns[1][data]=artist_name&draw=1')
165+
expected = (15, 15, 'Elvis Presley')
166+
result = response.json()
167+
self.assertEquals((result['recordsFiltered'], result['recordsTotal'], result['data'][0]['artist_name']), expected)
168+
169+
@override_settings(REST_FRAMEWORK={
170+
'DEFAULT_PAGINATION_CLASS': 'rest_framework_datatables.pagination.DatatablesLimitOffsetPagination',
171+
})
172+
def test_limitoffset_pagination_invalid_start1(self):
173+
AlbumViewSet.pagination_class = DatatablesLimitOffsetPagination
174+
client = APIClient()
175+
response = client.get(
176+
'/api/albums/?format=datatables&length=10&start=abc&columns[0][data]=name&columns[1][data]=artist_name&draw=1')
177+
expected = (15, 15, 'The Beatles')
178+
result = response.json()
179+
self.assertEquals((result['recordsFiltered'], result['recordsTotal'], result['data'][0]['artist_name']), expected)
180+
181+
@override_settings(REST_FRAMEWORK={
182+
'DEFAULT_PAGINATION_CLASS': 'rest_framework_datatables.pagination.DatatablesLimitOffsetPagination',
183+
})
184+
def test_limitoffset_pagination_invalid_start2(self):
185+
AlbumViewSet.pagination_class = DatatablesLimitOffsetPagination
186+
client = APIClient()
187+
response = client.get(
188+
'/api/albums/?format=datatables&length=10&start=-999&columns[0][data]=name&columns[1][data]=artist_name&draw=1')
189+
expected = (15, 15, 'The Beatles')
190+
result = response.json()
191+
self.assertEquals((result['recordsFiltered'], result['recordsTotal'], result['data'][0]['artist_name']), expected)
192+
193+
@override_settings(REST_FRAMEWORK={
194+
'DEFAULT_PAGINATION_CLASS': __name__ + '.DatatablesLimitOffsetPaginationCustomMax',
195+
})
196+
def test_limitoffset_pagination_invalid_max(self):
197+
AlbumViewSet.pagination_class = DatatablesLimitOffsetPaginationCustomMax
198+
client = APIClient()
199+
response = client.get(
200+
'/api/albums/?format=datatables&length=20&start=10&columns[0][data]=name&columns[1][data]=artist_name&draw=1')
201+
expected = (15, 15, 'Elvis Presley')
202+
result = response.json()
203+
self.assertEquals((result['recordsFiltered'], result['recordsTotal'], result['data'][0]['artist_name']), expected)
204+
111205
@override_settings(REST_FRAMEWORK={
112206
'DEFAULT_PAGINATION_CLASS': 'rest_framework_datatables.pagination.DatatablesLimitOffsetPagination',
113207
})

0 commit comments

Comments
 (0)