我们要实现如下样子的分页界面
pagination ui在不借助于第三方Django APP的情况下,仅仅使用Django框架提供的分页(Pagination)机制,该如何做呢?
视图中的分页处理
下面展示如何在视图中使用Paginator对一个queryset进行分页。假如我们需要对单品展示进行分页,单品的model叫做SKU.
from django.shortcuts import render
from django.core.paginator import PageNotAnInteger, Paginator, EmptyPage
def list_skus(request):
skus = SKU.objects.all()
# 分页,每页展示32项
paginator = Paginator(skus, 32)
page = request.GET.get('page')
try:
skus = paginator.page(page)
except PageNotAnInteger:
# 如果page不是整数,则展示第1页
skus = paginator.page(1)
except EmptyPage:
# 如果page超过范围,则展示最后一页
skus = paginator.page(paginator.num_pages)
return render(request, 'list_skus.html', {'skus': skus})
模板中的分页处理
上面的视图示例中最后会渲染模板list_skus.html,在该模板(使用Bootstrap框架)中,分页示例如下:
<div class="btn-group" role="group">
<!-- 第一页 -->
<a class="btn btn-default" href="?{{query_params.urlencode}}&page=1">
<span class="glyphicon glyphicon-step-backward"></span>
</a>
<!-- 上一页 -->
{% if skus.has_previous %}
<a class="btn btn-default" href="?{{query_params.urlencode}}&page={{skus.previous_page_number}}">
<span class="glyphicon glyphicon-chevron-left"></span>
</a>
{% else %}
<a class="btn btn-default disabled">
<span class="glyphicon glyphicon-chevron-left"></span>
</a>
{% endif %}
<!-- 当前页/总页数 -->
<a class="btn btn-default disabled">
<span>{{skus.number}} of {{skus.paginator.num_pages}}</span>
</a>
<!-- 下一页 -->
{% if skus.has_next %}
<a class="btn btn-default" href="?{{query_params.urlencode}}&page={{skus.next_page_number}}">
<span class="glyphicon glyphicon-chevron-right"></span>
</a>
{% else %}
<a class="btn btn-default disabled">
<span class="glyphicon glyphicon-chevron-right"></span>
</a>
{% endif %}
<!-- 最后一页 -->
<a class="btn btn-default" href="?{{query_params.urlencode}}&page={{skus.paginator.num_pages}}">
<span class="glyphicon glyphicon-step-forward"></span>
</a>
</div>
等等,上面模板中的query_params是什么鬼?为什么需要加上query_params?当我们对查询结果进行分页的时候,视图对应的URL地址一般会包含查询参数。这些查询参数不能丢,因此必须在视图和模板中显式地处理这些参数。视图中先获取查询参数,然后把查询参数放到上下文里面传给render方法。如下所示:
def list_skus(request):
# ...
query_params = request.GET.copy()
query_params.pop('page', None) # delete page param
# ...
context = {
'page': page,
'paginator': paginator,
'query_params': query_params,
'skus': skus,
}
return render(request, 'list_skus.html', context)
参考
网友评论