在网站开发时,肯定会遇到分页的事情需要处理,在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. Zabbix: Database Monitor Installation

    1.     Install ODBC MS SQL Connector On Zabbix Server    https://support.zabbix.com/browse/ZBX-6839 ...

  2. jenkins 安装配置: centos-master windows/linux-slave + nginx代理 + node + job

    centos install jenkins: 1.sudo vi /etc/yum.repos.d/jenkins.repo [jenkins] name=Jenkins baseurl=http: ...

  3. mysql 复制A表 到B表;insert into select * from table

    情况一: INSERT INTO tb1 (a,b,c) select a1,b1,c1, from tb2 where .... --  案例 百度云 INSERT INTO l_biz_car_o ...

  4. [HP-UNIX]bdf命令总结

    (1)bdf命令的效果 lijiaman$[/home/oracle]bdf Filesystem kbytes used avail %used Mounted on /dev/vg00/lvol3 ...

  5. leetcode笔记(三)207. Course Schedule

    题目描述(原题目链接) There are a total of n courses you have to take, labeled from 0 to n-1. Some courses may ...

  6. SAP销售订单屏幕字段控制隐藏,必输等

    1.T-CODE:shd0 创建变式  , 点击确认按钮后,SAP进入下一个屏幕,然后重复上面的操作,直到所有屏幕已完成设置. 如果后续屏幕不需要设置,可点击“退出并保存”按钮.保存后,进入下图所示页 ...

  7. MyEclipse格式化JSP代码,其中Javascript无法格式化的原因

    MyEclipse格式化JSP代码,其中Javascript无法格式化的原因: 可能是JSP页面代码有错误的地方,而且可能是一个很微小的错误,比如多写了一个标点符号,这个需要仔细检查,包括HTML.C ...

  8. Linux入门-第三周

    1.总结vim命令行模式常见快捷方式,以及vim查找,替换的方法 vim [options] [file ..] +# 打开文件后,让光标处于第#行的行首,(默认行尾) 举例vim +10 /etc/ ...

  9. 路由器基础配置之ospf基础配置

    我们将以上面的拓扑图进行本次ospf的实验,目的是能当三台pc机互通 先配置好pc机的IP地址,注意一定要给pc机设置好网关,接下来配置路由器的IP地址 router4 enable 进入特权模式 c ...

  10. nginx 只允许域名访问,禁止IP访问

    在nginx中为了防止,通过ip地址或者没有备案的域名代理到nginx上,可以在nginx中配置来阻止这一操作 #只可以用域名访问(此处的server是新增,并不是在原有的server基础上修改),默 ...