Pagination with JsonResponse
Use Django's Paginator
.
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
class ViewPaginatorMixin(object):
min_limit = 1
max_limit = 10
def paginate(self, object_list, page=1, limit=10, **kwargs):
try:
page = int(page)
if page < 1:
page = 1
except (TypeError, ValueError):
page = 1
try:
limit = int(limit)
if limit < self.min_limit:
limit = self.min_limit
if limit > self.max_limit:
limit = self.max_limit
except (ValueError, TypeError):
limit = self.max_limit
paginator = Paginator(object_list, limit)
try:
objects = paginator.page(page)
except PageNotAnInteger:
objects = paginator.page(1)
except EmptyPage:
objects = paginator.page(paginator.num_pages)
data = {
'previous_page': objects.has_previous() and objects.previous_page_number() or None,
'next_page': objects.has_next() and objects.next_page_number() or None,
'data': list(objects)
}
return data
Now, use the ViewPaginatorMixin
to support pagination for View
class ResultQueryView(ViewPaginatorMixin, View):
def get(self, request):
// code
serialized = ResourceSerializer(resources, many=True)
return JsonResponse({"resources": self.paginate(serialized.data, page, limit)})
A simple solution could be to slice serialized.data just before building JsonResponse (and maybe even annotate the result with total n. of expected pages, that is math.ceil(len(serialized.data) / PAGE_SIZE)
):
PAGE_SIZE = 10
start = page * PAGE_SIZE
stop = min(start + PAGE_SIZE, len(serialized.data))
#return JsonResponse({"resources": serialized.data})
return JsonResponse({"resources": serialized.data[start:stop]})
Test:
class FakeSerialized(object):
def __init__(self):
self.data = list(range(0,35))
serialized = FakeSerialized()
print('All data:', serialized.data)
PAGE_SIZE = 10
for page in range(0, 5):
start = page * PAGE_SIZE
stop = min(start + PAGE_SIZE, len(serialized.data))
data = serialized.data[start:stop]
print('Page %d:' % page, data)
Result:
$ python3 ./paginate.py
All data: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34]
Page 0: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Page 1: [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
Page 2: [20, 21, 22, 23, 24, 25, 26, 27, 28, 29]
Page 3: [30, 31, 32, 33, 34]
Page 4: []