在网站开发时,肯定会遇到分页的事情需要处理,在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. detection工作

    今天看到YOLO2的工作还是很不错的,效果好,关键是速度也快,已经完胜SSD了感觉. 虽然faster rcnn各方面效果都不错,但是从简单粗暴的角度考虑,SSD和YOLO真的深得我心啊. 检测模型, ...

  2. mui 的多图片上传

    pickHead(){ var _this = this; plus.gallery.pick(function(path){ _this.headImage=path; var files = [{ ...

  3. react(三):容器组件和傻瓜组件

    让一个组件只专注于一件事,如果发现让一个组件做的事情太多,就可以把这个组件拆分成多个组件让每一个组件只专注于一件事 <深入浅出react和redux> ---程墨 一个react组件最基本 ...

  4. vue富文本编辑,编辑自动预览,单个图片上传不能预览的问题解决:

    //预览<div class="htmlViewBox"> <p v-html="activity_html_defaultMsg" v-sh ...

  5. 18年selenium3+python3+unittest自动化测试教程(下)

    第六章 自动化测试进阶实战篇幅 1.自动化测试实战进阶之网页单选性别资料实战 简介:讲解使用selenium修改input输入框和单选框 2.自动化测试之页面常见弹窗处理 简介:讲解使用seleniu ...

  6. Knowledge Point 20180305 机器数转换与进制转换

    机器数(这里的机器数说的就是数值在计算机中的存储形式,相关可以了解数据在计算机中的表示)之间的转换往往是通过原码来实现的,下面我们结合进制来来一下: 进制也就是进位制,是人们规定的一种进位方法. 对于 ...

  7. oracle 分组函数、视图

    组函数 分组函数作用于一组数据,对每一组返回一个值 组函数类型: 1.计数        count(列名 或 表达式)     对满足的行数进行统计 2.求和        sum(列名 或 表达式 ...

  8. MySql Connector/c++8中JSON处理Demo

    #include <iostream> #include <vector> #include <mysqlx/xdevapi.h> using std::cout; ...

  9. 你的sql查询为什么这么慢?

    做后台开发的程序猿通常需要写各种各样的sql,可很多时候写出来的sql虽然能满足功能性需求,性能上却不尽人意.如果业务复杂,表结构和索引设计又不合理的话,写出来的sql执行时间可能会达到几十甚至上百秒 ...

  10. GET POST 请求的详细区别

    前言: 作为最常见的请求方式 在面试很有可能会被问到 所以在这里做一个简单总结 GET get方法向页面请求发送参数 地址和参数之间用?进行分割 例如 localhost:80/download.ht ...