系统地讲解Django开发的基础知识, 高阶知识。关注微信公众号[薯条编程],领取该教程的PDF电子书:《Python web开发-django从入门到精通》。
13.3.1 为什么需要分页
打开浏览器在搜索框中进行搜索,或者进入某电商平台的站内搜索页,输入关键词执行搜索以后可以在页面底部看到这样的分页按钮:
我们现在进入搜索页,输入关键词"Python"进行搜索,搜索引擎找到的相关页面多达7千万条,这么大的数据量无法在一个页面中进行显式,必须分页。我们在使用django开发网站时,也需要考虑到数据的分页显示,因为网站数据是不断增长的。
再者同学们在理解分页的时候,可以从多个角度来进行分析和理解。比如用户体验,页面加载时间,服务器负载,SEO等。
13.3.2 Paginator类
django提供了 Paginator类,所有进行分页处理的方法都基于Paginator。Paginator类的构造参数:
描述 | |
object_list | 对象列表 |
per_page | 每页的条目数 |
Paginator对象的常用属性:
属性名 | 描述 |
count | 整型,表示所有数据对象的数量 |
num_pages | 整型,表示分页的所有页数 |
page_range | range_iterator迭代器,表示分页的区间范围 |
Paginator对象的常用方法:
方法名 | 描述 |
page(number) | 参数number表示页码,函数返回一个page对象,page对象的object_list属性保存了当前页的所有数据。 |
has_next() | 返回一个布尔值,表示是否有下一页 |
has_previous() | 返回一个布尔值,表示是否有前一页 |
next_page_number() | 返回下一页的页码,如果没有下一页,会抛出异常 |
previous_page_number() | 返回前一页的页码,如果没有前一页,会抛出异常 |
start_index() | 返回当前页的开始索引,索引从1开始编号 |
end_index() | 返回当前页的结束索引,索引从1开始编号 |
现在进入Python交互模式,在交互模式中演示Paginator的主要用法:
>>> from django.core.paginator import Paginator
>>> objects = [{'title':'python', 'content':'i love python'}, {'title':'C++', 'content':'c++
is difficult'} ,
{'title':'Golang', 'content':'golang is great'}, {'title':'PHP', 'content':'php is the best language'}]
>>> p = Paginator(objects, 2)
>>> p.count
4
>>> p.num_pages
2
>>> type(p.page_range)
<class 'range_iterator'>
>>> p.page_range
range(1, 3)
>>> page1 = p.page(1)
>>> page1
<Page 1 of 2>
>>> page1.object_list
[{'title':'python', 'content':'i love python'}, {'title':'C++', 'content':'c++ is difficult'}]
>>> page2 = p.page(2)
>>> page2.object_list
[{'title':'Golang', 'content':'golang is great'}, {'title':'PHP', 'content':'php is the best language'}]
>>> page2.has_next()
False
>>> page2.has_previous()
True
13.3.3 在视图中使用Paginator
在视图中使用Paginator进行分页的简单例子:
# 导入Paginator类 from django.core.paginator import Paginator from django.shortcuts import render # 导入Article模型 from blog.models import Article # 定义listing函数用来对博客文章列表进行分页显式 def listing(request): article_list = Artile.objects.all() # 定义items_for_each_page变量,表示每页数据项的数目 items_for_each_page = 5 paginator = Paginator(article_list, items_for_each_page ) # 根据前端传递的page参数来进行分页 page_number = request.GET.get('page') page_obj = paginator.get_page(page_number) # 将page_obj对象传递至模板页article.html进行渲染 return render(request, 'article.html', {'page_obj': page_obj})
Article模型所对应的代码:
from django.db import models class Article(models.Model): author = models.CharField(max_length=20) title = models.CharField(max_length=50) content = models.TextField()
为了方便测试django分页,同学们可以将Article模型注册到后台管理系统,然后在后台管理系统中,手动地插入十条数据。article.html所对应的代码:
{% for article in page_obj %} <h2> {{ artile.title }} </h2> <p>{{ artile.content }} </p> {% endfor %} {# 分页的核心代码 #} <div> <span> {% if page_obj.has_previous %} <a href="?page=1">« 第一页</a> <a href="?page={{ page_obj.previous_page_number }}">前一页</a> {% endif %} <span> Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}. </span> {% if page_obj.has_next %} <a href="?page={{ page_obj.next_page_number }}">下一页</a> <a href="?page={{ page_obj.paginator.num_pages }}">尾页»</a> {% endif %} </span> </div
13.3.4 使用ListView进行分页
django同时提供了ListView来进行分页,其分页处理基于Paginator。使用ListView进行分页处理,更快捷,代码也更简洁。通常的做法是继承于该视图类,并在子类中进行配置。django会根据配置信息,自动添加一个paginator和page_obj的对象在视图的context对象中。对于ListView的用法,直接参考下面的代码实例:
from django.views.generic import ListView from blog.models import Article # 定义一个视图类ArticleList, 继承于ListView class ArticleList(ListView): # paginate_by属性用来配置每页显示的数据条数 paginate_by = 5 # model属性用来配置模型 model = Article # template_name用来配置模板 template_name = 'article.html'
关注微信公众号:薯条编程,回复"Python资料",免费领取Python电子书,以及学习Python视频课程。
小班授课,薯条老师一对一教学,火热报名中,点击了解线下就业培训。