django中的自定义分页器
1.什么是自定义分页器
当我们需要在前端页面展示的数据太多的时候,我们总不能将数据展示在一页上面吧!这时,我们就需要自定义一个分页器,将数据分成特定的页数进行展示,每一页展示固定条数的数据!

2.为什么要用自定义分页器
如上所说:为了将数据分成多页进行展示,分别阅读,方便查询!

3.如何使用自定义分页器
3.1 自定义分页器推导过程
虽然!我们有一个封装好的分页器源码,用的时候只需要cv大法就行,但是作为一名优秀的程序猿!!我们还是需要知道底层的逻辑是不是!!

我们需要明确的是,前端向后端请求的常用方式为get和post请求。分页的时候,我们应该采用get请求的方式给后端传输您需要转到的页数!!
其次我们还需要知道一个点,queryset对象是支持索引取值和切片操作的,但是不支持负数索引情况。
接下来,我们来推导一下分页器的形成的逻辑:
current_page = request.GET.get("page",1)  # 获取用户想访问的页码  如果没有 默认展示第一页
try:  # 由于后端接受到的前端数据是字符串类型所以我们这里做类型转换处理加异常捕获
  current_page = int(current_page)
except Exception as e:
  current_page = 1
# 还需要定义页面到底展示几条数据
per_page_num = 10  # 一页展示10条数据
# 需要对总数据进行切片操作 需要确定切片起始位置和终止位置
start_page = ?
end_page = ?
"""
下面需要研究current_page、per_page_num、start_page、end_page四个参数之间的数据关系
per_page_num = 10
current_page                start_page                  end_page
    1                           0                           10
    2                           10                          20
    3                           20                          30
    4                           30                          40
per_page_num = 5
current_page                start_page                  end_page
    1                           0                           5
    2                           5                           10
    3                           10                          15
    4                           15                          20
可以很明显的看出规律
start_page = (current_page - 1) * per_page_num
end_page =  current_page* per_page_num
"""
我们研究完当前页(current_page)、每页展示的数据条数(per_page_num)、每页数据的起始位置(start_page)和结束位置(end_page)之后,我们还需要知道的最重要的一点是:
一共需要从数据库取出的数据一共有多少条!!!

此时,我们就需要用到python中的一个内置方法divmod:它是功能是一个数除以另一个数时,返回余数和商!!如:
>>> divmod(100,10)
(10, 0)  # 10页
>>> divmod(101,10)
(10, 1)  # 11页
>>> divmod(99,10)
(9, 9)  # 10页
# 余数只要不是0就需要在第一个数字上加一
我们可以用它来判断我们一共需要多少页!
后端自定义分页器逻辑详解:
def book(request):
    if request.method == 'GET':
        current_page = request.GET.get('page',1) # 获取用户需要访问的页面,如果没有默认返回1
    try:   #异常捕获,因为前端返回的都是字符串,需要把他们都转成数字类型,方便下面做运算操作
        current_page = int(current_page)
    except Exception as e:
        current_page = 1  # 用户输入啥字母等也默认为1
    per_page_num = 10  #每页展示多少条数据
    start_page = (current_page - 1) * per_page_num  #当前页数起始数据
    end_page = current_page * per_page_num  #当前页结束数据
    book_num = models.Book.objects.all() #将所有数据查询出来
    all_count = book_num.count()  # 统计一共有多少数据
    num,more = divmod(all_count,per_page_num)  #divmod方法计算需要的总页数
    if more:
        all_page = num + 1 #more为余数,余为0,则刚刚好是num页数,不为0,则页数加1
    # 然后我们需要在html页面的分页器标签部分,for循环一下总共需要的num页数,但是有一个问题是,前端无法使用range()
    # 这就需要我们在后端进行循环,再传到前端
    html = ''
    a = current_page # 为了下面页码高亮调整
    if current_page <6:  #当页面小于6时,固定在6上面,为下面的for处理不出现页码负数
        current_page = 6
    # 访问第6页时,只会显示当前页-5和+6的底部页码数,但是当页面小于6时,页码会出现0甚至负数,所有我们需要对页面进行一个设置,就是上述的a
    for i in range(current_page-5,current_page+6):
        if a == i:
            # 当前页的页面高亮显示
            html += '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i)
        else:
            html += '<li><a href="?page=%s">%s</a></li>' % (i, i)
    book_queryset = book_num[start_page:end_page]
    return render(request,'book.html',locals())
前端页面部分:
<nav aria-label="Page navigation">
  <ul class="pagination">
    <li>
      <a href="#" aria-label="Previous">
        <span aria-hidden="true">«</span>
      </a>
    </li>
        {{ html|safe }}
    <li>
      <a href="#" aria-label="Next">
        <span aria-hidden="true">»</span>
      </a>
    </li>
  </ul>
</nav>
3.2 自定义分页器封装代码
封装好的分液器
class Pagination(object):
    def __init__(self, current_page, all_count, per_page_num=2, pager_count=11):
        """
        封装分页相关数据
        :param current_page: 当前页
        :param all_count:    数据库中的数据总条数
        :param per_page_num: 每页显示的数据条数
        :param pager_count:  最多显示的页码个数
        """
        try:
            current_page = int(current_page)
        except Exception as e:
            current_page = 1
        if current_page < 1:
            current_page = 1
        self.current_page = current_page
        self.all_count = all_count
        self.per_page_num = per_page_num
        # 总页码
        all_pager, tmp = divmod(all_count, per_page_num)
        if tmp:
            all_pager += 1
        self.all_pager = all_pager
        self.pager_count = pager_count
        self.pager_count_half = int((pager_count - 1) / 2)
    @property
    def start(self):
        return (self.current_page - 1) * self.per_page_num
    @property
    def end(self):
        return self.current_page * self.per_page_num
    def page_html(self):
        # 如果总页码 < 11个:
        if self.all_pager <= self.pager_count:
            pager_start = 1
            pager_end = self.all_pager + 1
        # 总页码  > 11
        else:
            # 当前页如果<=页面上最多显示11/2个页码
            if self.current_page <= self.pager_count_half:
                pager_start = 1
                pager_end = self.pager_count + 1
            # 当前页大于5
            else:
                # 页码翻到最后
                if (self.current_page + self.pager_count_half) > self.all_pager:
                    pager_end = self.all_pager + 1
                    pager_start = self.all_pager - self.pager_count + 1
                else:
                    pager_start = self.current_page - self.pager_count_half
                    pager_end = self.current_page + self.pager_count_half + 1
        page_html_list = []
        # 添加前面的nav和ul标签
        page_html_list.append('''
                    <nav aria-label='Page navigation>'
                    <ul class='pagination'>
                ''')
        first_page = '<li><a href="?page=%s">首页</a></li>' % (1)
        page_html_list.append(first_page)
        if self.current_page <= 1:
            prev_page = '<li class="disabled"><a href="#">上一页</a></li>'
        else:
            prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1,)
        page_html_list.append(prev_page)
        for i in range(pager_start, pager_end):
            if i == self.current_page:
                temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i,)
            else:
                temp = '<li><a href="?page=%s">%s</a></li>' % (i, i,)
            page_html_list.append(temp)
        if self.current_page >= self.all_pager:
            next_page = '<li class="disabled"><a href="#">下一页</a></li>'
        else:
            next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1,)
        page_html_list.append(next_page)
        last_page = '<li><a href="?page=%s">尾页</a></li>' % (self.all_pager,)
        page_html_list.append(last_page)
        # 尾部添加标签
        page_html_list.append('''
                                           </nav>
                                           </ul>
                                       ''')
        return ''.join(page_html_list)
3.3 封装好分页器的使用
后端
 def get_book(request):
   book_list = models.Book.objects.all()
   current_page = request.GET.get("page",1)
   all_count = book_list.count()
   page_obj = Pagination(current_page=current_page,all_count=all_count,per_page_num=10)
   page_queryset = book_list[page_obj.start:page_obj.end]
   return render(request,'booklist.html',locals())
前端
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            {% for book in page_queryset %}
            <p>{{ book.title }}</p>
            {% endfor %}
            {{ page_obj.page_html|safe }}
        </div>
    </div>
</div>
django中的自定义分页器的更多相关文章
- Django中的自定义过滤器
		一.为什么要自定义Django中的自定义过滤器:Django中提供了很多内置的过滤器和标签,详见链接django官网,主要有以下几个: autoescape(自动转义)block(模板继承)csrf_ ... 
- Django基础之自定义分页器
		自定义分页器 针对批量插入的数据,我们在前端展示的时候发现一个很严重的问题,一页展示了所有的数据,数据量太大,查看不方便 针对数据量大但又需要全部展示给用户观看的情况下,我们统一做法都是做分页处理 分 ... 
- 在django中使用自定义标签实现分页功能
		效果演示: github地址:https://github.com/mncu/django_projects/tree/master/django_projects/pagination_test 本 ... 
- Laravel 中通过自定义分页器分页方法实现伪静态分页链接以利于 SEO
		我们知道,Laravel 自带的分页器方法包含 simplePaginate 和 paginate 方法,一个返回不带页码的分页链接,另一个返回带页码的分页链接,但是这两种分页链接页码都是以带问号的动 ... 
- 在 Laravel 中通过自定义分页器分页方法实现伪静态分页链接以利于 SEO
		我们知道,Laravel 自带的分页器方法包含 simplePaginate 和 paginate 方法,一个返回不带页码的分页链接,另一个返回带页码的分页链接,但是这两种分页链接页码都是以带问号的动 ... 
- Django 中的自定义分页标签
		目录结构: 1.在应用下,migrations的同级目录创建templatetags目录(主要两个文件,包含__init__.py) 2.创建分页标签(pagetag.py) #!/usr/bin/e ... 
- Django中配置自定义日志系统
		将 
- Django 中自定义用户模型及集成认证授权功能总结
		1. 概述 Django 中的 django.contrib.auth 应用提供了完整的用户及认证授权功能. Django 官方推荐基于内置 User 数据模型创建新的自定义用户模型,方便添加 bir ... 
- Django分页器及自定义分页器
		Django的分页器 view from django.shortcuts import render,HttpResponse # Create your views here. from app0 ... 
随机推荐
- BERT的优化演进方法汇总(持续更新)
			模型结构演进 本文以演进方向和目的为线索梳理了一些我常见到但不是很熟悉的预训练语言模型,首先来看看"完全版的BERT":RoBERTa: A Robustly Optimized ... 
- Spring boot中最大连接数、最大线程数与最大等待数在生产中的异常场景
			在上周三下午时,客户.业务和测试人员同时反溃生产环境登录进入不了系统,我亲自测试时,第一次登录进去了,待退出后再登录时,复现了客户的问题,场景像是请求连接被拒绝了,分析后判断是spring boot的 ... 
- 【原创】渗透神器CoblatStrike实践(1)
			渗透神器CoblatStrike实践(1) 前言 正常的渗透测试:  寻找漏洞,利用漏洞,拿到一定的权限 后渗透(CS为代表的):  提升权限,内网渗透,权限维持 工具地址(非官方取到后门多,建议 ... 
- 【ASP.NET Core】配置应用程序地址的N多种方法
			下面又到了老周误人子弟的时间,今天要误大伙的话题是:找找有多少种方法可以设置 ASP.NET Core 应用的地址,即 URL. 精彩马上开始! 1.UseUrls 方法 这是一个扩展方法,参数是可变 ... 
- 【clickhouse专栏】clickhouse性能为何如此卓越
			在<clickhouse专栏>上一篇文章中<数据库.数据仓库之间的区别与联系>,我们介绍了什么是数据库,什么是数据仓库,二者的区别联系.clickhouse的定位是" ... 
- Centos6添加防火墙端口 以及相关操作命令的使用
			用命令 vim /etc/sysconfig/iptables 增加防火墙端口号:(添加你需要的端口号) service iptables start 启动防火墙 service iptables ... 
- 皓远的第二次博客作业(最新pta集,链表练习及期中考试总结)
			前言: 知识点运用:正则表达式,有关图形设计计算的表达式和算法,链表的相关知识,Java类的基础运用,继承.容器与多态. 题量:相较于上次作业,这几周在java方面的练习花了更多的精力和时间,所要完成 ... 
- flink 流的合并
			flink 流的合并操作 union union只能合并类型相同的数据,合并的结果仍然是DataStream,结果操作与未合并之前一致. public static void main(String[ ... 
- js 表面使用 表面学习 -输出
			JavaScript 能够以不同方式"显示"数据: 使用 window.alert() 写入警告框 使用 document.write() 写入 HTML 输出 使用 innerH ... 
- flex大法:一网打尽所有常见布局
			flex全称Flexible Box模型,顾名思义就是灵活的盒子,不过一般都叫弹性盒子,所有PC端及手机端现代浏览器都支持,所以不用担心它的兼容性,有了这玩意,妈妈再也不用担心我们的布局. 先简单介绍 ... 
