Django是一个非常全面的Web框架,也预置了分页的功能,这点稍后介绍。然而,我并不想按照Django给的分页功能来做。学习一个东西最好学习它的本质。分页的原理其实很简单,就是根据你传入的参数从数据库获取一部分的数据来展示。比如按照5篇文章来分页,每次就从数据库取5条数据,然后返回给前端展示即可。
models的配置,并且一经使用了makemigrations和migrate同步了数据库中的表
class Host(models.Model): name = models.CharField(max_length=10) ip = models.GenericIPAddressField() def __str__(self): return self.name
view的设置
def batch(request, page): page = transfer2int(page, 1) count = Host.objects.count() per_item = transfer2int(request.COOKIES.get("pageNum", 30), 30) print("每页的大小", per_item) # 总页数 page_num = math.ceil(count/per_item) if page > page_num: page = page_num elif page <= 0: page = 1 # 本页的开始 start = (page - 1) * per_item end = min(page * per_item, count) hosts = Host.objects.all()[start:end] print("page", page) print(hosts) if page_num <= 11: startIndex = 1 endIndex = page_num else: if page <6: startIndex = 1 endIndex = 11 elif page + 5 > page_num: endIndex = page_num startIndex = page_num - 10 else: startIndex = page - 5 endIndex = page + 5 return render(request, "batch.html", {"hosts": hosts, "count": count, "bars": range(startIndex, endIndex+1), "page_num": page_num, "page": page}
page是从url出接收到的页码,也就是第几页,函数transfer2int是为了将字符串page转成数值型
def transfer2int(arg, default): try: result = int(arg) except ValueError as e: result = default return result
count是表中的总记录数
per_item是每页有多少条记录
page_num是总页数
hosts 是查询好的数据记录信息
为了页面显示友好,也可以展示 页码条,当前是总共展示11个选择
页面配置信息
{% load staticfiles %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>分页</title>
<script type="text/javascript" src="{% static ‘js/jquery-3.1.1.js‘ %}"></script>
<script type="text/javascript" src="{% static ‘js/jquery.cookie.js‘ %}"></script>
<style type="text/css">
table, td{
border: solid 1px blueviolet;
}
#paging a{
background-color: green;
border: white solid 1px;
text-decoration: none;
color: white;
}
#paging a.selected{
color: red;
}
</style>
</head>
<body>
<table>
<tr>
<td>主机名</td>
<td>IP</td>
</tr>
{% for host in hosts %}
<tr>
<td>{{ host.name }}</td>
<td>{{ host.ip }}</td>
</tr>
{% endfor %}
</table>
<div>总条数{{ count }}</div>
<select id="pageNum" onchange="changePageNum();">
<option value="10">10</option>
<option value="20">20</option>
<option value="30">30</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
<div id="paging">
{% if page_num == 1 %}
<a href="/shop/batch/1/">1</a>
{% else %}
{% if page > 1 %}
<a href="/shop/batch/1/">首页</a>
{% endif %}
{% if page >= 2 %}
<a href="/shop/batch/{{ page|add:-1 }}/">上一页</a>
{% endif %}
{% for bar in bars %}
{% if page == bar %}
<a href="/shop/batch/{{ bar }}/" class="selected">{{ bar }}</a>
{% else %}
<a href="/shop/batch/{{ bar }}/">{{ bar }}</a>
{% endif %}
{% endfor %}
{% if page < page_num %}
<a href="/shop/batch/{{ page|add:1 }}/">下一页</a>
<a href="/shop/batch/{{ page_num }}/">尾页</a>
{% endif %}
{% endif %}
</div>
<script type="text/javascript">
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
$(function () {
var pageNum = $.cookie("pageNum");
if (pageNum>0){
$("#pageNum").val(pageNum);
} else {
$("#pageNum").val(30);
}
});
</script>
</body>
</html>
原来我使用了ajax,在本例中没有使用。ajax在下篇随笔中会说明。
django分页的关键使用了
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
关键是view中的编写
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger def batch2(request): page = transfer2int(request.GET.get(‘page‘), 1) count = Host.objects.count() per_item = 10 print("每页的大小", per_item) all_host = Host.objects.all() paginator = Paginator(all_host, per_item) # Show 25 contacts per page try: hosts = paginator.page(page) except PageNotAnInteger: # If page is not an integer, deliver first page. hosts = paginator.page(1) except EmptyPage: # If page is out of range (e.g. 9999), deliver last page of results. hosts = paginator.page(paginator.num_pages) return render(request, "batch2.html", {"hosts":hosts})
页面如下
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>django分页</title> </head> <body> {% for host in hosts %} {{ host.name }}<br> {% endfor %} <div class="pagination"> <span class="step-links"> {% if hosts.has_previous %} <a href="?page={{ hosts.previous_page_number }}">previous</a> {% endif %} <span class="current"> Page {{ hosts.number }} of {{ hosts.paginator.num_pages }}. </span> {% if hosts.has_next %} <a href="?page={{ hosts.next_page_number }}">next</a> {% endif %} </span> </div> </body> </html>
还有一个问题没有解决哦,因为肯定有朋友会问,如果一个列表有100000个item, 我们想要实现每页40个,那么,当将我们请求该列表时,paginator 在分页过程中,请求数据库是取40个,还是取100000啊!显然,paginator 是不可能取100000的啦。paginator 巧妙的利用了Django延迟获取数据的特性,因此,paginator 每次取数据都是只取每页的数据的(也就是上例中的40个),所以是不会有性能 影响 的哦。
官方文档 https://docs.djangoproject.com/en/1.10/topics/pagination/
原文:http://www.cnblogs.com/yangshl/p/6383247.html