通过 Django Pagination 实现简单分页功能


Posted in Python onNovember 11, 2019

通过 Django Pagination 实现简单分页功能

作者:HelloGitHub-追梦人物

文中所涉及的示例代码,已同步更新到 HelloGitHub-Team 仓库

当博客上发布的文章越来越多时,通常需要进行分页显示,以免所有的文章都堆积在一个页面,影响用户体验。

Django 内置的 Pagination 能够帮助我们实现简单的分页功能,在上一篇教程中我们使用脚本批量生成了几百篇博客文章,正好用于测试分页效果。

Paginator 类的常用方法

分页功能由 Django 内置的 Paginator 类提供,这个类位于 django.core.paginator 模块,需要使用它时,只需在适当的地方导入这个类即可:

from django.core.paginator import Paginator

下面的代码摘自 Django 的官方文档中 Pagination 的示例,只需实例化一个 Paginator 对象,并在实例化时传入一个需要分页的列表对象,就可以得到分页后的对象。

# 对 item_list 进行分页,每页包含 2 个数据。
>>> item_list = ['john', 'paul', 'george', 'ringo']
>>> p = Paginator(item_list, 2)

取特定页的数据:

# 取第 2 页的数据
>>> page2 = p.page(2)
>>> page2.object_list
['george', 'ringo']

查询特定页的当前页码数:

>>> page2.number
2

查看分页后的总页数:

>>> p.num_pages
2

查看某一页是否还有上一页,以及查询该页上一页的页码:

# 查询第二页是否还有上一页
>>> page2.has_previous()
True

# 查询第二页上一页的页码
>>> page2.previous_page_number()
1

查看某一页是否还有下一页,以及查询该页下一页的页码:

# 查询第二页是否还有下一页
>>> page2.has_next()
False

# 查询第二页下一页的页码
>>> page2.next_page_number()
Traceback (most recent call last):
...
EmptyPage: That page contains no results

更多方法和属性请参阅 Django Pagination 的官方文档。

用 Paginator 给文章列表分页

使用上面的一些方法,我们可以实现一个类似于 Django 官方博客一样的简单分页效果,效果如下。

通过 Django Pagination 实现简单分页功能

这里 Django 的官方文档中给出了一个在视图函数中对列表进行分页的示例,这个视图函数获取一个联系人列表并对其分页:

from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from django.shortcuts import render

def listing(request):
  contact_list = Contacts.objects.all()
  paginator = Paginator(contact_list, 25) # 每页显示 25 个联系人

  page = request.GET.get('page')
  try:
    contacts = paginator.page(page)
  except PageNotAnInteger:
    # 如果用户请求的页码号不是整数,显示第一页
    contacts = paginator.page(1)
  except EmptyPage:
    # 如果用户请求的页码号超过了最大页码号,显示最后一页
    contacts = paginator.page(paginator.num_pages)

  return render(request, 'list.html', {'contacts': contacts})

这就是在视图函数中使用分页的代码逻辑,你可以把它当做一个模板应用于自己的任何需要分页的视图函数。不过在我们的博客项目中,我们不必写这些代码了。回顾在 Django 官方推荐的姿势:类视图 中的内容,我们已将视图函数转换成了类视图。而类视图 ListView 已经帮我们写好了上述的分页逻辑,我们只需通过指定 paginate_by 属性来开启分页功能即可,即在类视图中指定 paginate_by 属性的值:

blog/views.py

class IndexView(ListView):
  model = Post
  template_name = 'blog/index.html'
  context_object_name = 'post_list'
  # 指定 paginate_by 属性后开启分页功能,其值代表每一页包含多少篇文章
  paginate_by = 10

这里我们设置了每 10 篇文章一页。

在模板中设置分页导航

接下来便是在模板中设置分页导航,比如上一页、下一页的按钮,以及显示一些页面信息。我们这里设置和 Django 官方博客那样的分页导航样式(具体的样式见上图)。ListView 传递了以下和分页有关的模板变量供我们在模板中使用:

  • paginator ,即 Paginator 的实例。
  • page_obj ,当前请求页面分页对象。
  • is_paginated,是否已分页。只有当分页后页面超过两页时才算已分页。
  • object_list,请求页面的对象列表,和 post_list 等价。所以在模板中循环文章列表时可以选 post_list ,也可以选 object_list

模板中使用示例:

templates/blog/index.html

{% if is_paginated %}
<div class="pagination-simple">
 <!-- 如果当前页还有上一页,显示一个上一页的按钮 -->
 {% if page_obj.has_previous %}
  <a href="?page={{ page_obj.previous_page_number }}">上一页</a>
 {% endif %}
 <!-- 显示当前页面信息 -->
 <span class="current">第 {{ page_obj.number }} 页 / 共 {{ paginator.num_pages }} 页</span>
 <!-- 如果当前页还有下一页,显示一个下一页的按钮 -->
 {% if page_obj.has_next %}
  <a href="?page={{ page_obj.next_page_number }}">下一页</a>
 {% endif %}
</div>
{% endif %}

其中 {{ }} 模板变量中的内容,其含义已在文章开头部分的 Paginator 类的常用方法中已有介绍。另外还要注意一点,请求哪一个页面通过 page 查询参数传递给 django 视图,django 会根据 page 的值返回对应页面的文章列表,所以上一页和下一页超链接的 href 属性指向的 url 带上了 page 查询参数。

最终我们得到如下的分页效果:

通过 Django Pagination 实现简单分页功能

当然这只是一个简单示例,分页导航处的视觉效果并不是很好看,你可以自行为其添加 CSS 样式使其看上去更加美观。

进一步拓展

使用 Django 内置的 Pagination 只能实现上面的简单分页效果,但通常更加高级的分页效果应该像下图这样:

通过 Django Pagination 实现简单分页功能

当前页面高亮显示,且显示当前页面前后几页的页码,始终显示第一页和最后一页的页码,中间可能还有省略号的效果,表示还有未显示的页码。

仅仅使用 Django Pagination 内置的方法无法实现这样的效果,需要自己写分页逻辑或者借助第三方库。接下来我们将详细说明如何借助第三方库拓展 Pagination 以实现一个完善的分页效果。

总结

以上所述是小编给大家介绍的通过 Django Pagination 实现简单分页功能,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

Python 相关文章推荐
MySQLdb ImportError: libmysqlclient.so.18解决方法
Aug 21 Python
Python简单遍历字典及删除元素的方法
Sep 18 Python
Python列表list内建函数用法实例分析【insert、remove、index、pop等】
Jul 24 Python
python入门前的第一课 python怎样入门
Mar 06 Python
python opencv3实现人脸识别(windows)
May 25 Python
Python实现提取XML内容并保存到Excel中的方法
Sep 01 Python
python使用Plotly绘图工具绘制气泡图
Apr 01 Python
python虚拟环境完美部署教程
Aug 06 Python
Python collections模块的使用方法
Oct 09 Python
Python人工智能之混合高斯模型运动目标检测详解分析
Nov 07 Python
代码复现python目标检测yolo3详解预测
May 06 Python
python标准库ElementTree处理xml
May 20 Python
python机器学习实现决策树
Nov 11 #Python
Python SQLAlchemy入门教程(基本用法)
Nov 11 #Python
django中间键重定向实例方法
Nov 10 #Python
Java文件与类动手动脑实例详解
Nov 10 #Python
python语言线程标准库threading.local解读总结
Nov 10 #Python
Python 脚本拉取 Docker 镜像问题
Nov 10 #Python
Python如何优雅获取本机IP方法
Nov 10 #Python
You might like
PHP常用设计模式之委托设计模式
2016/02/13 PHP
Zend Framework动作助手Redirector用法实例详解
2016/03/05 PHP
HTTP头隐藏PHP版本号实现过程解析
2020/12/09 PHP
php的对象传值与引用传值代码实例讲解
2021/02/26 PHP
用js写了一个类似php的print_r输出换行功能
2013/02/18 Javascript
js将long日期格式转换为标准日期格式实现思路
2013/04/07 Javascript
js中使用replace方法完成某个字符的转换
2014/08/20 Javascript
jquery实现textarea输入框限制字数的方法
2015/01/15 Javascript
js简单抽奖代码
2015/01/16 Javascript
js实现鼠标感应图片展示的方法
2015/02/27 Javascript
JS给Textarea文本框添加行号的方法
2015/08/20 Javascript
Javascript中判断一个值是否为undefined的方法详解
2016/09/28 Javascript
EasyUI学习之DataGird分页显示数据
2016/12/29 Javascript
JS实现给json数组动态赋值的方法示例
2020/03/19 Javascript
vue中使用iview自定义验证关键词输入框问题及解决方法
2018/03/26 Javascript
30分钟快速入门掌握ES6/ES2015的核心内容(上)
2018/04/18 Javascript
一篇文章介绍redux、react-redux、redux-saga总结
2019/05/23 Javascript
微信小程序制作扭蛋机代码实例
2019/09/24 Javascript
基于Vue全局组件与局部组件的区别说明
2020/08/11 Javascript
解决removeEventListener 无法清除监听的问题
2020/10/30 Javascript
微信小程序实现弹幕墙(祝福墙)
2020/11/18 Javascript
Python标准库defaultdict模块使用示例
2015/04/28 Python
使用 Python 实现文件递归遍历的三种方式
2018/07/18 Python
python开启摄像头以及深度学习实现目标检测方法
2018/08/03 Python
将Python字符串生成PDF的实例代码详解
2019/05/17 Python
python3 requests库实现多图片爬取教程
2019/12/18 Python
俄罗斯旅游网站:Tripadvisor俄罗斯
2017/03/21 全球购物
TripAdvisor越南:全球领先的旅游网站
2017/09/21 全球购物
瑞典的玛丽小姐:Miss Mary of Sweden
2019/02/13 全球购物
mysql的最长数据库名,表名,字段名可以是多长
2014/04/21 面试题
是什么让J2EE适合用来开发多层的分布式的应用
2015/01/16 面试题
旅游专业职业生涯规划范文
2014/01/13 职场文书
《夜晚的实验》教学反思
2014/02/19 职场文书
会走路的树教学反思
2014/02/20 职场文书
Java8中接口的新特性使用指南
2021/11/01 Java/Android
Nginx本地配置SSL访问的实例教程
2022/05/30 Servers