作者:HelloGitHub-追梦人物

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

通过 Django Pagination 实现简单分页 中,我们实现了一个简单的分页导航。但效果有点差强人意,我们只能点上一页和下一页的按钮进行翻页。比较完善的分页效果应该像下面这样,但想实现这样一种效果,Django Pagination 内置的 API 已无能为力。接下来我们将通过拓展 Django Pagination 来实现下图这样比较完善的分页效果。

分页效果概述

一个比较完善的分页效果应该具有以下特性,就像上图展示的那样,很多网站都采用了类似这种的分页导航方式。

  • 始终显示第一页和最后一页。
  • 当前页码高亮显示。
  • 显示当前页码前后几个连续的页码。
  • 如果两个页码号间还有其它页码,中间显示省略号以提示用户。

分页思路

如果需要自己来实现分页效果,我们会怎么做呢?先来分析一下导航条的组成部分,可以看到整个分页导航条其实可以分成 7 个部分:

  1. 第 1 页页码,这一页需要始终显示。
  2. 第 1 页页码后面的省略号部分。但要注意如果第 1 页的页码号后面紧跟着页码号 2,那么省略号就不应该显示。
  3. 当前页码的左边部分,比如这里的 3-4。
  4. 当前页码,比如这里的 5。
  5. 当前页码的右边部分,比如这里的 6-7。
  6. 最后一页页码前面的省略号部分。但要注意如果最后一页的页码号前面跟着的页码号是连续的,那么省略号就不应该显示。
  7. 最后一页的页码号。

因此我们的思路是,在视图中依据上述规则生成页码列表,然后在模板中循环显示页码列表就可以了。有了思路,实现起来其实也并不很难。不过对于这类常见需求,别人早就帮我们实现好了,本着不重复造轮子的原则,直接拿来用就好。

第一个 Django 第三方拓展:django-pure-pagination

我们第一次开始接触 django 第三方拓展,在此之前我们一直都基于 django 本身我们提供的功能在开发,然而 django 强大的地方就在于海量的第三方应用供我们挑选,几乎大部分 web 开发中的需求,django 都能找到他人已经写好的第三方应用,拿来即用。

事实上,正确的 django 开发姿势应该是这样的:

  1. 充分理解你的需求,想一想,如果自己实现,我会怎么做?
  2. 通过 Google、GitHub、开发者社区论坛等调研已有的实现类似需求的应用
  3. 拿来即用,并尝试理解他人是如何实现这个功能的

以我们的分页功能举例:

首先我们上面分析了分页需求的实现。然后我在 GitHub 上通过 django pagination 关键词进行搜索,在比较了多个 star 数比较高的项目后,发现 django-pure-pagination 文档最清晰,使用最简单,因此决定将这个应用集成到我们的博客来。值得一提的是,尽管这个应用显示作者最后一次更新代码在 4 年前,但我粗略浏览了一下源码,发现其依赖的 django api 4 年来异常稳定,所以确保能在 django 2.2 中使用。

接下来我们就来使用它,首先安装它:

$ pipenv install django-pure-pagination

然后将它注册到 INSTALLED_APPS 里:

INSTALLED_APPS = [
# ...
'pure_pagination', # 分页 'blog.apps.BlogConfig', # 注册 blog 应用
'comments.apps.CommentsConfig', # 注册 comments 应用
]

修改一下 IndexView,让它继承 django-pure-pagination 提供的 PaginationMixin,这个混入类将为我们提供上述提到的分页功能。

class IndexView(PaginationMixin, ListView):
model = Post
template_name = 'blog/index.html'
context_object_name = 'post_list'
paginate_by = 10

然后我们可以在 common.py 配置中配置一下分页的效果,这是 django-pure-pagination 提供的配置项,用于个性化配置分页效果:

# django-pure-pagination 分页设置
PAGINATION_SETTINGS = {
'PAGE_RANGE_DISPLAYED': 4, # 分页条当前页前后应该显示的总页数(两边均匀分布,因此要设置为偶数),
'MARGIN_PAGES_DISPLAYED': 2, # 分页条开头和结尾显示的页数
'SHOW_FIRST_PAGE_WHEN_INVALID': True, # 当请求了不存在页,显示第一页
}

在模板中需要分页的地方,调用分页对象的 render 方法就可以了,比如在 index.html 中:

{% if is_paginated %}
{{ page_obj.render }}
{% endif %}

注意这里 page_obj 是分页后的对象列表,具体请参考上一篇文章的讲解。render 方法会自动帮我们渲染一个预先定义好的分页条,至此,分页功能就完成了。

自定义模板

有时候预定义的分页条并不能满足我们的需求,我们可以通过自定义的模板来覆盖预定义的模板。django 查找模板的顺序是,首先在项目配置的模板根路径寻找(我们项目中配的是 templates 文件夹),没有找到的话,再去应用的 templates 目录下寻找。分页模板预定义的路径为 pure_pagination/pagination.html,所以我们可以在项目模板根路径下建立一个一模一样的文件结构,这样 django 就会首先找到我们的模板,从而应用我们自定义的模板,而不是预定义的模板。

在 templates 目录下新建一个 pure_pagination\ 目录,然后建立一个 pagination.html 文件。

接下来便是在模板中设置分页导航了,将导航条的七个部分的数据一一展现即可,示例代码如下:

<div class="text-center pagination" style="width: 100%">
<ul>
{% if page_obj.has_previous %}
<li><a href="?{{ page_obj.previous_page_number.querystring }}"
class="prev">&lsaquo;&lsaquo; </a></li>
{% else %}
<li><span class="disabled prev">&lsaquo;&lsaquo; </span></li>
{% endif %}
{% for page in page_obj.pages %}
{% if page %}
{% ifequal page page_obj.number %}
<li class="current"><a href="#">{{ page }}</a></li>
{% else %}
<li><a href="?{{ page.querystring }}" class="page">{{ page }}</a></li>
{% endifequal %}
{% else %}
...
{% endif %}
{% endfor %}
{% if page_obj.has_next %}
<li><a href="?{{ page_obj.next_page_number.querystring }}" class="next"> &rsaquo;&rsaquo;</a>
</li>
{% else %}
<li><span class="disabled next"> &rsaquo;&rsaquo;</span></li>
{% endif %}
</ul>
</div>

多添加几篇文章,在示例中就可以看到分页效果了。要使分页导航更加美观,通过设置其 CSS 样式即可。


『讲解开源项目系列』——让对开源项目感兴趣的人不再畏惧、让开源项目的发起者不再孤单。跟着我们的文章,你会发现编程的乐趣、使用和发现参与开源项目如此简单。欢迎留言联系我们、加入我们,让更多人爱上开源、贡献开源~

稳定易用的 Django 分页库,完善分页功能的更多相关文章

  1. python 学习笔记十八 django深入学习三 分页,自定义标签,权限机制

    django  Pagination(分页) django 自带的分页功能非常强大,我们来看一个简单的练习示例: #导入Paginator>>> from django.core.p ...

  2. 26.Django模板语言和分页

    继承 extends 子版只能继承一个父模板 1.父模板 master.html <!DOCTYPE html> <html lang="en"> < ...

  3. 4.Django模板语言和分页

    继承 extends 子版只能继承一个父模板 1.父模板 master.html <!DOCTYPE html> <html lang="en"> < ...

  4. meteor中分页库alethes:pages用法汇总

    1.添加分页库: meteor add alethes:pages 2.新建分页: Pages = new Meteor.Pagination("collection-name") ...

  5. Django的rest_framework的分页组件源码分析

    前言: 分页大家应该都很清楚,今天我来给大家做一下Django的rest_framework的分页组件的分析:我的讲解的思路是这样的,分别使用APIview的视图类和基于ModelViewSet的视图 ...

  6. python 全栈开发,Day87(ajax登录示例,CSRF跨站请求伪造,Django的中间件,自定义分页)

    一.ajax登录示例 新建项目login_ajax 修改urls.py,增加路径 from app01 import views urlpatterns = [ path('admin/', admi ...

  7. [django]drf知识点梳理-分页

    msyql分页 limit offset https://www.cnblogs.com/iiiiiher/articles/8846194.html django自己实现分页 https://www ...

  8. django项目一 分页器(前端分页和后端分页区别)

    1. 客户信息展示 1. 母版和继承 {% extends 'layout'%} {% load static%} {% static '文件路径' %} block css js content 2 ...

  9. Django Rest framework 之 分页

    RESTful 规范 django rest framework 之 认证(一) django rest framework 之 权限(二) django rest framework 之 节流(三) ...

随机推荐

  1. HTML建立超链接

      链接是HTML文档的最基本特征之一.超文本链接英文名为hyperlink,它能够让浏览器在各个独立的页面之间方便地跳转.超链接有外部链接.电子邮件链接.锚点链接等. a标签   网页中<a& ...

  2. vue使用talkIngData统计

    上篇刚使用了百度统计,由于后端同事没有找到百度统计的api,于是就找了个talkingData平台... 平台地址 依旧是先注册 进入应用统计分析  创建应用 获得appid 在vue中埋点 1.in ...

  3. 使用Java窗口程序执行输入的任何cmd命令

    利用Java窗口程序来执行用输入的任何命令 实现效果: Java桌面窗口,输入框.按钮,当输入框被输入命令的时候,点击按钮执行命令! 实现代码 package com.remote.remote.ag ...

  4. 【Linux系列】Centos 7安装 PHP(四)

    目的 为了下面的Laravel部署,本篇开始安装PHP. 设置PHP源 查看Centos源是否有PHP. yum list php* 进一步查看PHP的版本. yum info php.x86_64 ...

  5. Rust 入门 (三)_上

    这部分我们学习 rust 语言的 变量.数据类型.函数.注释.流程控制 这五个方面的内容.本文我们介绍前两个内容,下一篇文章介绍后三个内容. 变量 默认情况下,rust 语言中声明的变量是不可变的,比 ...

  6. java的回调和C#的委托

    曾经有人对我说java的回调很巧妙. 今天我自己看了一下,回调的关键就是一个接口的事情. 也许是因为用了一定的手法,一开始不好懂吧,所以看懂了会感觉巧妙. 但是我心里的想法却是,真啰嗦! 回调的实例 ...

  7. Java基础语法(二)

    目录 一.强类型语言 二.数据类型分类 1.基本数据类型 整数类型 字符类型 浮点类型 布尔类型 2.引用数据类型 三.基本类型转换 自动类型转换 强制类型转换 四.表达式类型的自动提升 承接上篇,谈 ...

  8. 解决failed to push some refs to 'git@github.com:TQBX/GIT-Github-.git'问题

    解决以下问题问题: git pull origin master --allow-unrelated-histories 进入vim界面->ESC->:wq 重复第一步->git p ...

  9. solr数据操作

    本文介绍solr的基本数据操作,基于solr 8.2.solr支持多种数据格式,包括XML,JSON,CSV等,并提供多种脚本和工具来操作数据.本文讲解curl请求和JSON数据格式的处理方式. 本文 ...

  10. java Random类详解

    java Random类位于java.util包下,主要用来生成随机数,本文详解介绍了Random类的用法,希望能帮到大家 Random类 (java.util) Random类中实现的随机算法是伪随 ...