Django基础之自定义分页器
自定义分页器
针对批量插入的数据,我们在前端展示的时候发现一个很严重的问题,一页展示了所有的数据,数据量太大,查看不方便
针对数据量大但又需要全部展示给用户观看的情况下,我们统一做法都是做分页处理

分页推导
首先我们需要明确的时候,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
"""

数据总页面获取
当我问你下面几个问题的时候,你的内心肯定是鄙视的,不信的话那就请听题
问题1:总数据有100条,每页展示10条,总共需要几页?
答案:10条
问题2:总数据有101条,每页展示10条,总共需要几页?
答案:11条
问题3:如何通过代码算出到底需要多少条?
答案:去你妹的,不会!!!

内置方法之divmod
>>> divmod(100,10)
(10, 0) # 10页
>>> divmod(101,10)
(10, 1) # 11页
>>> divmod(99,10)
(9, 9) # 10页
# 余数只要不是0就需要在第一个数字上加一
我们可以判断元祖的第二个数字是否为0从而确定到底需要多少页来展示数据 book_queryset = models.Book.objects.all()
all_count = book_queryset.count() # 数据总条数
all_pager, more = divmod(all_count, per_page_num)
if more: # 有余数则总页数加一
all_pager += 1
至此分页器大致的功能及思路我们就已经大致清楚了 最后我们只需要利用start_page和end_page对总数据进行切片取值再传入前端页面就能够实现分页展示 book_list = models.Book.objects.all()[start_page:end_page]
return render(request,'booklist.html',locals())
接下来就是前端页面的代码编写了 {% for book in book_list %}
<p>{{ book.title }}</p>
{% endfor %}
现在我们实现了最简单的分页,但是前端没有按钮去让用户点击需要看第几页,所以我们需要渲染分页器相关代码,这里我们不做要求直接去bootstrap框架拷贝代码即可

终极大法
上面是自定义分页器开发流程的基本思路,我们不需要掌握代码的编写,只需要掌握基本用法即可
自定义分页器封装代码
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)
自定义分页器使用
后端
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中的自定义分页器
1.什么是自定义分页器 当我们需要在前端页面展示的数据太多的时候,我们总不能将数据展示在一页上面吧!这时,我们就需要自定义一个分页器,将数据分成特定的页数进行展示,每一页展示固定条数的数据! 2.为什 ...
- django自定义分页器
一 django 的分页器 1 批量创建数据 批量导入数据: Booklist=[] for i in range(100): Booklist.append(Book(title="boo ...
- {Django基础九之中间件} 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证
Django基础九之中间件 本节目录 一 前戏 二 中间件介绍 三 自定义中间件 四 中间件的执行流程 五 中间件版登陆认证 六 xxx 七 xxx 八 xxx 一 前戏 我们在前面的课程中已经学会了 ...
- Django分页器和自定义分页器
一.自定义分页器 import copy class Pagination(): def __init__(self,request,current_page,all_data_num,each_pa ...
- Django分页器及自定义分页器
Django的分页器 view from django.shortcuts import render,HttpResponse # Create your views here. from app0 ...
- Django框架第九篇--Django和Ajax、序列化组件(serializers)、自定义分页器、模型表choice参数
Django和Ajax 一.什么是Ajax AJAX(Asynchronous Javascript And XML)翻译成中文就是“异步的Javascript和XML”.即使用Javascript语 ...
- Django基础(2)--模板自定义标签和过滤器,模板继承 (extend),Django的模型层-ORM简介
没整理完 昨日回顾: 视图函数: request对象 request.path 请求路径 request.GET GET请求数据 QueryDict {} request.POST POST请求数据 ...
- day 65 Django基础之django分页
Django基础之django分页 一.Django的内置分页器(paginator) view from django.shortcuts import render,HttpRespons ...
- day 61 Django基础之django分页
Django基础之django分页 一.Django的内置分页器(paginator) view from django.shortcuts import render,HttpRespons ...
随机推荐
- (CV学习笔记)Attention
Attention(注意力机制) Attention for Image Attention for Machine Translation Self-Attention 没有image-Attent ...
- 多线程-4.wait() notify() notifyAll() 生产者消费者模型
1.wait()方法 该方法继承于Object类.在调用obj.wait()方法后,当前线程会失去obj的锁.待其他线程调用obj.notify()或notifyAll()方法后进入锁等待池,争抢到锁 ...
- GDI编程基础
窗口和视口 视口是基于设备的采用的是设备坐标(单位:像素),窗口是基于程序的采用的是逻辑坐标(单位:像素/毫米/厘米等). 在默认的映射模式下,视口是与窗口等同的.但是如果改变其映射模式,则其对应的单 ...
- [bug] kafka启动报错 could not be established. Broker may not be available.
原因 配置文件和命令行中的主机名不一致,建议都用ip地址 参考 https://blog.csdn.net/getyouwant/article/details/79000524
- [笔记] 《c++ primer》显示器程序 Chapter7
补充Sales_data没有体现出的其他类特性 Screen.h 1 #include <string> 2 #include <iostream> 3 4 class Scr ...
- 2020 Kali Linux Zenmap 安装(可视化界面)
跟着教程学Kali Linux,我安装的2020版的,发现Zemap没被预装. 1.下载 zenmap https://nmap.org/download.html 2.rpm转deb 2020 Ka ...
- Python基础 小白[7天]入门笔记
笔记来源 Day-1 基础知识(注释.输入.输出.循环.数据类型.随机数) #-*- codeing = utf-8 -*- #@Time : 2020/7/11 11:38 #@Author : H ...
- liveCD版: CD光盘映像,和liveDVD一样,唯一的区别就是该版本中包含的软件包会少一点,安装系统时使用 U 盘或者CD光盘进行安装。
https://man.linuxde.net/download/CentOS/ CentOS,英文全称"Community Enterprise Operating System" ...
- 009.kubernets的调度系统之污点和容忍
Taints和Tolerations(污点和容忍) Taint需要与Toleration配合使用,让pod避开那些不合适的node.在node上设置一个或多个Taint后,除非pod明确声明能够容忍这 ...
- 6.5 scp:远程文件复制
scp命令 用于在不同的主机之间复制文件,它采用SSH协议来保证复制的安全性.scp命令每次都是全量完整复制,因此效率不高,适合第一次复制时使用,增量复制建议使用rsync命令替代. scp ...