有不少初学Django的朋友经常抱怨,在网上搜了一大堆教程,各种自定也分页的方法对新手一点都不友好,很难看懂。那今天我来写一个相对容易看懂的教程吧。
django内置paginator分页器虽然用起来是很简单,但是功能也很简单。一旦数据多起来,就会把页码分列成好几行,极不美观。那么要想自己限定当前最多显示前后多少页码,那要不就是重写paginator中的一些方法,或者用Listview。
但今天我更推荐初学者自己尝试自定义一个分页方法:
LIST = []
for i in range(209):
LIST.append(i)
#这里就不用数据库的数据了,用个列表来举例,假设列表里有209条数据
def url_list(request):
#url_list是我临时起的视图名称,大家按照自己urls.py里面对应url写就行
current_page = request.GET.get('p',1)
current_page = int(current_page)
#获取当前页码
total_count = len(LIST)
#数据总长度
per_page = 10
#每页显示多少条数据
max_page = 11
#页面上始终保持最多显示多少页码
start = (current_page-1) * per_page
end = current_page * per_page
#数据展示的起始点和结束点
total_page,y = divmod(total_count,per_page)
if y:
total_page += 1
#divmod()方法要是不知道就百度吧,用来整除和取余数用的。也就是假设每页10条数据,
#那么209条数据可以分多少页,那么用209整除10就行了,要是有余数,就加一页,
#余数也就是'y',总页数是'total_page'
if current_page > total_page:
current_page = total_page
#如果当前页码比总页数还大,那就限定当前页等于总页数,不然你会有无穷的页码
if max_page > total_page:
max_page = total_page
#如果最大页码也大于总页数,那就以说明数据量很少,分不足11页,那就让分页范围是总页数
half_max_page = max_page -1// 2
#half_max_page代表当前页码的前后各有多少页
start_page = current_page - half_max_page
end_page = current_page + half_max_page
#起始页和结束页
if start_page <= 1:
start_page = 1
end_page = max_page
#如果起始页比1还小,那就定起始页显示为1,结束页为最大显示页数11,也就是【1、2、
3、4、5、6、7、8、9、10、11】,否则会出现负数页数显示在页面上
if end_page > total_page:
end_page = total_page
start_page = total_page - max_page +1
#如果结束页比总页数还大,那就定结束页为最后一页,起始页为总页数前10页,比如说总页数是20,那就是【10、11、12、13、14、15、16、17、18、19、20】,这是防止出现20页以后还出现更大的页码
data = LIST[start:end]
#这里就基本设置好了每页对应显示哪几条数据了,data是用来接收的变量,最后用来渲染的
page_str = []
#先创建一个空列表,用来接收等下要插入的html标签,最后渲染到模板里
page_str.append('<div class="page"><a href="/url_list/?p=1">首页</a></div>')
if current_page <= 1:
page_str.append('<div class="page hide"><a href="/url_list/?p=%s">上一页</a></div>'%(current_page-1))
else:
page_str.append('<div class="page"><a href="/url_list/?p=%s">上一页</a></div>'%(current_page-1))
#如果当前页是第一页,那就不存在“上一页”的按钮了
for i in range(start_page,end_page):
if i == current_page:
temp = '<div class="page active"><a href="/url_list/?p=%s">%s</a></div>' %(i,i)
else:
temp = '<div class="page"><a href="/url_list/?p=%s">%s</a></div>' %(i,i)
page_str.append(temp)
#重点来了,这里的range(start_page,end_page)就是上面我们自己通过计算的出来的前后分页
if current_page >= total_page:
page_str.append('<div class="page hide"><a href="/url_list/?p=%s">下一页</a></div>'%(current_page+1))
else:
page_str.append('<div class="page"><a href="/url_list/?p=%s">下一页</a></div>'%(current_page+1))
page_str.append('<div class="page"><a href="/url_list/?p=%s">尾页</a></div>'%(total_page))
page_html = "".join(page_str)
#最后一定要拼接成字符串,再渲染,不然会出现很多类似'['的符号在网页上,你懂的
return render(request,'url_list.html',{'data':data,'page_html':page_html})
还有在templates里的:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.page{
margin: 5px;
background-color: pink;
float: left }
.active{
background-color: blue }
.hide{
display: none }
</style>
</head>
<body>
<ul>
{% for i in data %}
<li>{{i}}</li>
{% endfor %}
</ul>
{{page_html|safe}}
</body>
</html>
这样的大功告成了,你完全可以先把代码复制进去,自己试一下。至于网页的样式,完全是可以自己自定义的。
注意事项:
另外,其实像这种分页功能,理解了原理就行了,你不可能以后工作的时候动不动就几十行代码就为了个分页功能。这里给大家推荐一个我本人自己常用的“轮子”:EasyPage,只需要设置5各参数,分页想怎么设置就怎么设置,
原理和上面的代码一样,只是我自己封装成class了,用起来方便许多。
EasyPage地址:https://github.com/ChrisLee0211/django-EasyPage(具体用法都写在里面了,很简单的)