源起
我想要优雅地使用bootstrap
+ django pagination
来实现分页,忽然发现不知道该如何做起 我照葫芦画瓢知道了bootstrap
怎么使用列表组件,也大概知道怎么使用pagination
,但是放到一起我就彻底懵逼了。
资料收集
bootstrap
基本分页演示
<div class="pagination">
<ul>
<li><a href="#">Prev</a></li>
<li><a href="#">1</a></li>
<li><a href="#">2</a></li>
<li><a href="#">3</a></li>
<li><a href="#">4</a></li>
<li><a href="#">5</a></li>
<li><a href="#">Next</a></li>
</ul>
</div>
如果想使用禁用和活动状态,可以使用".disable"
和".active"
选项。
参见:bootstrap分页说明.
Pageination
可以做的事情
首先,Paginator是一个类,它初始化时接受一个列表或者元组或者是Django的查询结果集(queryset
),以及分组大小,然后生成一个具有一系列属性的对象。下面的代码演示了如何初始化以及操作Pageination
对象,不要担心示例里操作的是列表,完全可以拿来操作查询结果。
from django.core.paginator import Paginator
objects = ['john', 'paul', 'george', 'ringo']
p = Paginator(objects, 2)
print(p.count) #4
print(p.num_pages)#2
print(p.page_range) #range(1,3),2.x是[1,2]
page1 = p.page(1)
page1
<Page 1 of 2>
page1.object_list
['john', 'paul']
page2 = p.page(2)
page2.object_list #['george', 'ringo']
page2.has_next() #False
page2.has_previous() #True
page2.has_other_pages()#True
page2.next_page_number()#返回错误信息
page2.previous_page_number()#1
page2.start_index() # 本页的第一个项:3
page2.end_index() # 本页的最后一个项:4
p.page(0)
Traceback (most recent call last):
'''
上面的例子可以看到一些有价值的信息,Paginator对象可以返回count计数,num_pages页数,以及一个枚举对象page_range,分页大小:p.per_page。作为当前页,p.page(1),可以退单上一页和下一页,本页的开始和结束序号、
'''
可以在接受到适当的请求时,向模板返回一个适当的分页对象上下文,模板根据上下文来生成分页
初步构想的模板文件。
模板中迭代pages生成分页html代码
实践
花了点时间初步实现了下,本来就是很简单的东西,没什么好说的,为了方便演示,使用列表代替Queryset
作为查询对象
视图函数
#views.py
from django.shortcuts import render
from django.core.paginator import Paginator
#上下文将pages,current_page传入到模板文件中
def page_view(request,page_number = '1'):
#看到这个不用困惑,就当成教材里的pages=Article.objects.all()这样的查询结果好了
pages = list(range(100))
p = Paginator(pages,8)
current_page = p.page(int(page_number))
context ={'pages':p,'current_page':current_page}
return render(request,'blogs/page.html',context)
URL配置
#这里一切从简,只是为了制造一个可以传入参数的,形式为/page/{number}的url而已,如果你不明白
#我在做什么,那说什么都是多余的
from django.conf.urls import url
from blogs import views
urlpatterns = [
url(r'^page/(?P<page_number>\d+)$',views.page_view,name = "page"),
]
模板配置
//假定传入了分页器pages和当前页current_page.
<!--这里集成模板导入的bootstrap js和css就不展示了-->
{% extends 'blogs/base.html' %}
{% block page_block %}
<ul class = 'pagination'>
//首先如果有前一页,则生成前一页
{% if current_page.has_previous %}
<li class = 'previous'>
<a href = {{ current_page.previous_page_number }}>上一页</a>
</li>
{% endif %}
{% for number in pages.page_range %}
<li
{% if number == current_page.number %}
class = "activate"
{% endif %}>
<a href = {{ number }}>{{ number }}</a>
</li>
{% endfor %}
//让后如果当前页有后一页,则生成后一页
{% if current_page.has_next %}
<li class = 'next'>
<a href = {{ current_page.next_page_number }}>下一页</a>
</li>
{% endif %}
</ul>
{% endblock %}
最终结果
最后
这个效果怎么说呢,django自带的模板看起来和jinjia2很像,实际上有那么一点变扭。
bootstrap生成列表不用太费神,但是一次显示这么多分页似乎也不是很妥,还可以缩减下可视的列表范围