• django视图之分页


    在网站开发时,肯定会遇到分页的事情需要处理,在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>
    使用上述两种方法基本可以完成分页的业务需求

  • 相关阅读:
    套接字编程,创建套接字socket
    网络编程基本原理
    进一步学习的书籍
    C# 基础备忘录
    二进制转文件以及文件压缩和解压缩
    使用用WCF中的双工(Duplex)模式将广告图片推送到每个Winform客户端机子上
    C#两个日期范围内的间隔
    C#中XML文档注释编译DLL引用到其它项目
    用T4模版生成对应数据库表的实体类
    lodop打印控件需要开启的几个计算机服务
  • 原文地址:https://www.cnblogs.com/limaomao/p/9501465.html
Copyright © 2020-2023  润新知