在网站开发时,肯定会遇到分页的事情需要处理,在django中也是如此,在Django中处理分页一般会使用到两个类django.core.paginator.Paginator和django.core.paginator.Page,要想在Django中做分页处理,首先我们就需要了解一下这两个类。
首先在使用Django的通用视图时,在get_context_data方法中返回的内容中就包含当前页的分类信息,get_context_data方法的返回值中封装了当前页的分页信息,即Paginator和Page类的对象。其中Paginator被封装成的对象对应的键为'paginator',Page被封装成的对象对应的键为'page_obj'

Paginator类对象常用属性和方法,主要是整个列表相关信息:
  count:总共有多少条数据。
  num_pages:总共有多少页。
  page_range:页面的区间。比如有三页,那么就range(1,4)。

Page类对象常用属性和方法,主要是当前页相关信息:
  has_next():是否还有下一页。
  has_previous():是否还有上一页。
  next_page_number():下一页的页码。
  previous_page_number():上一页的页码。
  number:当前页码。
  start_index():当前这一页的第一条数据的索引值。
  end_index():当前这一页的最后一条数据的索引值。

普通分页:在手动写分页的时候,我们只需要使用到原生的Paginator和Page类对象,而这些对象直接被封装在get_context_data的返回值之中,我们直接使用就可以了,借助于bootstrap的分页相关样式,在模板中的代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>文章列表</title>
{# 引入bootstrap样式 #}
  <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
  <ul>
{# 列表内容 #}
    {% for article in article_list %}
      <li>
        {{ article.title }}
      </li>
    {% endfor %}
  <ul class="pagination">
{# 分页内容 #}
{# 上一页 #}
    {% if page_obj.has_previous %}
      <li><a href="{% url 'front:article_list' %}?page={{ page_obj.previous_page_number }}">上一页</a></li>
    {% else %}
      <li class="disabled"><a href="javascript:void(0);">上一页</a></li>
    {% endif %}
{# 中间页 #}
    {% for num_page in paginator.page_range %}
      {% if page_obj.number == num_page %}
        <li class="active"><a href="{% url 'front:article_list' %}?page={{ num_page }}">{{ num_page }}</a></li>
      {% else %}
        <li><a href="{% url 'front:article_list' %}?page={{ num_page }}">{{ num_page }}</a></li>
      {% endif %}
    {% endfor %}
{# 下一页 #}
    {% if page_obj.has_next %}
      <li><a href="{% url 'front:article_list' %}?page={{ page_obj.next_page_number }}">下一页</a></li>
    {% else %}
      <li class="disabled"><a href="javascript:void(0);">下一页</a></li>
    {% endif %}
  </ul>
</ul>
</body>
</html>

上面的分页写法,如果页数过于多,那么将会很难看,而且也不是很实用,所以上面的分页写法只适合于很少的页数的分页,不是通用的写法,下面我们就来编写一种通用的分页写法

通用分页算法:通用分页算法需要我们对原始的Paginator和Page对象进行进一步的封装,使用封装后的数据进行分页,首先我们写一个函数去封装这两个对象,例如get_pagination_data:

def get_context_data(self, **kwargs):
  context = super(ArticleListView, self).get_context_data(**kwargs)
  paginator = context.get('paginator') # 包含整体数据的相关信息
  page_obj = context.get('page_obj') # 包含当前页数据相关的信息
  pagination_data = self.get_pagination_data(paginator, page_obj)
  context.update(pagination_data)
  return context

def get_pagination_data(self, paginator, page_obj, around_count=2):
  left_has_more = False
  right_has_more = False
  current_page = page_obj.number
  if current_page <= around_count + 2:
    left_range = range(1, current_page)
  else:
    left_has_more = True
    left_range = range(current_page-around_count,current_page)

  if current_page >= paginator.num_pages - around_count-1:
    right_range = range(current_page+1, paginator.num_pages+1)
  else:
    right_has_more = True
    right_range = range(current_page+1, current_page+around_count+1)

  pagination_data = {
    'left_has_more': left_has_more,
    'right_has_more': right_has_more,
    'left_range': left_range,
    'right_range': right_range
  }
  return pagination_data

在模板使用封装的数据,去进行分页,示例代码如下:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>文章列表</title>
  <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<ul>
  {% for article in article_list %}
  <li>
    {{ article.title }}
  </li>
  {% endfor %}
  <ul class="pagination">
{# 上一页 #}
    {% if page_obj.has_previous %}
      <li><a href="{% url 'front:article_list' %}?page={{ page_obj.previous_page_number }}">上一页</a></li>
    {% else %}
      <li class="disabled"><a href="javascript:void(0);">上一页</a></li>
    {% endif %}
{# 中间左边部分 #}
    {% if left_has_more %}
      <li><a href="{% url 'front:article_list' %}?page=1">1</a></li>
      <li><a href="javascript:void(0);">...</a></li>
    {% for page in left_range %}
      <li><a href="{% url 'front:article_list' %}?page={{ page }}">{{ page }}</a></li>
    {% endfor %}
    {% else %}
    {% for page in left_range %}
      <li><a href="{% url 'front:article_list' %}?page={{ page }}">{{ page }}</a></li>
    {% endfor %}
    {% endif %}
{# 中间部分当前页 #}
      <li class="active"><a href="{% url 'front:article_list' %}?page={{ page_obj.number }}">{{ page_obj.number }}</a></li>
{# 中间右边部分 #}
    {% if right_has_more %}
    {% for page in right_range %}
      <li><a href="{% url 'front:article_list' %}?page={{ page }}">{{ page }}</a></li>
    {% endfor %}
      <li><a href="javascript:void(0);">...</a></li>
      <li><a href="{% url 'front:article_list' %}?page={{ paginator.num_pages }}">{{ paginator.num_pages }}</a></li>
    {% else %}
    {% for page in right_range %}
      <li><a href="{% url 'front:article_list' %}?page={{ page }}">{{ page }}</a></li>
    {% endfor %}
    {% endif %}
{# 下一页 #}
    {% if page_obj.has_next %}
      <li><a href="{% url 'front:article_list' %}?page={{ page_obj.next_page_number }}">下一页</a></li>
    {% else %}
      <li class="disabled"><a href="javascript:void(0);">下一页</a></li>
    {% endif %}
  </ul>
</ul>
</body>
</html>
使用上述两种方法基本可以完成分页的业务需求

django视图之分页的更多相关文章

  1. django之快速分页

    本文介绍djanog两种分页,第一是普通分页,第二是使用haystack全文检索的分页. 1.django自带分页功能,这个功能非常好用.基本知识点:Django提供了数据分页的类,这些类被定义在dj ...

  2. Django中的分页,cookies与session

    cookie Cookie的由来 大家都知道HTTP协议是无状态的. 无状态的意思是每次请求都是独立的,它的执行情况和结果与前面的请求和之后的请求都无直接关系,它不会受前面的请求响应情况直接影响,也不 ...

  3. django: django rest framework 分页

    django: django rest framework 分页 2018年06月22日 13:41:43 linux_player_c 阅读数:665更多 所属专栏: django 实战   版权声 ...

  4. django: rest-framework的 分页和过滤

    django: rest-framework的 分页和过滤 2018年06月28日 10:09:01 weixin_42359464 阅读数:136 标签: flaskrestframeworkdja ...

  5. django上课笔记2-视图CBV-ORM补充-Django的自带分页-Django的自定义分页

    一.视图CBV 1.urls url(r'^login.html$', views.Login.as_view()), 2.views from django.views import View cl ...

  6. Django视图扩展类

    Django视图扩展类 扩展类必须配合GenericAPIView使用扩展类内部的方法,在调用序列化器时,都是使用get_serializer 需要自定义get.post等请求方法,内部实现调用扩展类 ...

  7. Django - Xadmin (三) 分页、搜索和批量操作

    Django - Xadmin (三) 分页.搜索和批量操作 分页和 ShowList 类 因为 list_view 视图函数里面代码太多,太乱,所以将其里面的用于处理表头.处理表单数据的关键代码提取 ...

  8. Django 内置分页的简单使用

    1, 文档 https://docs.djangoproject.com/en/1.11.1/topics/pagination/ 2,视图 from django.core.paginator im ...

  9. [diango]理解django视图工作原理

    前言:正确理解django视图view,模型model,模板的概念及其之间的关联关系,才能快速学习并上手使用django制作网页 本文主要讲解自己在学习django后对视图view的理解 在进入正文之 ...

随机推荐

  1. TIDB1 —— TiDB简介

    TiDB 兼容 MySQL,支持无限的水平扩展,具备强一致性和高可用性. TiDB 具备如下核心特点: 1 高度兼容 MySQL  大多数情况下,无需修改代码即可从 MySQL 轻松迁移至 TiDB, ...

  2. IP检验字段为啥只检验地址部分

    在首部中的错误比在数据中的错误更重 如:一个错误的地址可能导致分组被投递到错误的主机.许多主机并不检查投递给它们的分组是否 确定是要投递给它们,它们假定网络从来不会把别人的分组包传递给自己.数据不参加 ...

  3. JSTL&EL

    JSTL <1> 实现了JSP页面代码的复用 <2> 使得可读性更强 导入 <%@ taglib uri="http://java.sun.com/jsp/js ...

  4. Mbatis错误信息整理

        ***每存在一对接口和xml文件,必须在xml文件中定义好mapper标签及namespace     ***每对接口必须和xml文件名必须一致 <mapper>标签中的names ...

  5. Navicat for Mysql中错误提示索引过长1071-max key length is 767 byte

    1.建用户信息表 tb_person_info create table tb_person_info( user_id int(10) auto_increment, `name` varchar( ...

  6. JavaScript--获取页面盒子中鼠标相对于盒子上、左边框的坐标

    分析: 外层边框是浏览器边框,内部盒子是页面的一个盒子,绿点是盒子中鼠标的位置.鼠标相对盒子边框的坐标=页面中(注意不是浏览器)鼠标坐标-盒子相对于浏览器边框的偏移量 第一步:求浏览器边框位置 x=e ...

  7. 服务器空间不足导致mysql服务器无法运行

    今天有朋友请我帮忙解决一个问题,他公司服务器mysql数据库一直连接失败.登录服务期之后发现服务器空间占满了,导致mysql不能启动. 下面说解决方法: 首先查看空间占用,发现空间占满了 df -h ...

  8. 源码安装CentOs7下的PHP7

    首先安装APACHE环境,直接用yum安装 yum install httpd httpd-devel /etc/httpd/ systemctl start httpd.service #启动apa ...

  9. Trie(字典树,前缀树)_模板

    Trie Trie,又经常叫前缀树,字典树等等. Trie,又称前缀树或字典树,用于保存关联数组,其中的键通常是字符串.与二叉查找树不同,键不是直接保存在节点中,而是由节点在树中的位置决定.一个节点的 ...

  10. FireDAC内存表

    procedure TForm1.FormCreate(Sender: TObject); Var i:integer; begin // i:=; self.FDMemTable1.FieldDef ...