我想为我的JsonResponse添加分页。
我目前正在使用django.http.JsonResponse
从弹性搜索API生成json。我想添加一个分页功能。我的代码如下:
class ResultQueryView(View):
def get(self, request):
resource_meta = request.GET.getlist("resource_meta")
locations = request.GET.getlist("location")
page = request.GET.get("page")
logger.info("Got search query where resource_meta: {} and locations: {}".format(resource_meta, locations))
results = resource_query(resource_meta, locations)
resource_ids = [r["_id"] for r in results['hits']['hits']]
resources = get_enriched_resources(request.user, Resource.objects.filter(internal_id__in=resource_ids))
serialized = ResourceSerializer(resources, many=True)
return JsonResponse({"resources": serialized.data})
答案 0 :(得分:7)
使用Django的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
现在,使用ViewPaginatorMixin
支持View
的分页
class ResultQueryView(ViewPaginatorMixin, View):
def get(self, request):
// code
serialized = ResourceSerializer(resources, many=True)
return JsonResponse({"resources": self.paginate(serialized.data, page, limit)})
答案 1 :(得分:1)
一个简单的解决方案是在构建JsonResponse之前切片serialized.data(甚至可以用预期页面总数n。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]})
测试:
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)
结果:
$ 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: []
答案 2 :(得分:0)
您可以覆盖get_queryset()
中的ListAPIView
,以返回根据您的需求构造的查询集,然后使用视图的内置分页:
from rest_framework.generics import ListAPIView
from rest_framework.pagination import PageNumberPagination
class ResultQueryView(ListAPIView):
serializer_class = ResourceSerializer
# configure this according to your needs
pagination_class = PageNumberPagination
def get_queryset(self):
resource_meta = self.request.GET.getlist("resource_meta")
locations = self.request.GET.getlist("location")
results = resource_query(resource_meta, locations)
resource_ids = [r["_id"] for r in results['hits']['hits']]
return Resource.objects.filter(internal_id__in=resource_ids))
答案 3 :(得分:0)
这只是您如何执行此操作的示例:
class nameClass(ListView):
paginate_by = 25
def get_paginate_by(self, queryset):
return self.request.GET.get('pag_num', self.paginate_by)
def get_context_data(self, **kwargs):
context = super(nameClass, self).get_context_data(**kwargs)
# we recover the number of pages
context['pages'] = self.request.GET.get('pag_num', self.paginate_by)
context['paginacion_personalizada'] = self.paginacion_personalizada
return context
def get_queryset(self):
queryset = super(CorreccionSSPList, self).get_queryset()
page_num = self.request.GET.get('pag_num', self.paginate_by)
page = self.request.GET.get('page', 1)
manager = MixinPaginator(queryset, page_num)
self.paginator = manager.get_paginator(page)
return queryset
maxin_paginator.py
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
class MixinPaginator:
def __init__(self, objects, count):
self.pages = Paginator(objects, count)
def get_paginator(self, page):
queryset = []
try:
queryset = self.pages.page(page)
except PageNotAnInteger:
queryset = self.pages.page(1)
except EmptyPage:
queryset = self.pages.page(1)
return queryset
在您的HTML中:
<div class="col-xs-6 col-md-3 right">
<select id="input_num_pag" class="form-control" data-page='{{ pages }}'>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</div>
答案 4 :(得分:0)
我回答这个可能有点晚了。但我使用 Django 的分页器类做到了
from django.core.paginator import Paginator
class ResultQueryView(View):
def get(self, request):
....
....
max_records_required_per_page = 10
queryset = Resource.objects.filter(internal_id__in=resource_ids)
serializer = ResourceSerializer(queryset, many=True)
p = Paginator(serializer.data, max_records_required_per_page)
response = p.page(actual_value_of_page).object_list
return JsonResponse({"resources": response})