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 ...
随机推荐
- Java虚拟机启动过程解析
一.序言 当我们在编写Java应用的时候,很少会注意Java程序是如何被运行的,如何被操作系统管理和调度的.带着好奇心,探索一下Java虚拟机启动过程. 1.素材准备 从Java源代码.Java字节码 ...
- git 无法拉取最新代码
删除本地文件后,想从远程仓库中重新新Pull最新代码,但是执行了git pull origin develop 命令后始终无法拉取下来 提示 Already up-to-date. 原因:当前本地库处 ...
- python常用标准库(os系统模块、shutil文件操作模块)
常用的标准库 系统模块 import os 系统模块用于对系统进行操作. 常用方法 os模块的常用方法有数十种之多,本文中只选出最常用的几种,其余的还有权限操作.文件的删除创建等详细资料可以参考官方文 ...
- MySQL锁(乐观锁、悲观锁、多粒度锁)
锁 并发事务可能出现的情况: 读-读事务并发:此时是没有问题的,读操作不会对记录又任何影响. 写-写事务并发:并发事务相继对相同的记录做出改动,因为写-写并发可能会产生脏写的情况,但是没有一个隔离级别 ...
- 2021.06.12【NOIP提高B组】模拟 总结
T1 题目大意:有 \(n\) 个点,到点 \(i\) 可以获得 \(A_i\) ,同时消耗 \(B_i\) 若当前价值小于 \(B_i\) 则不能到,问从 \(P\) 开始,任一点结束后的最大值. ...
- Vmware 10~16激活码/序列号 汇总
Vmware 16 ZF3R0-FHED2-M80TY-8QYGC-NPKYF YF390-0HF8P-M81RQ-2DXQE-M2UT6 ZF71R-DMX85-08DQY-8YMNC-PPHV8 ...
- 六、LVM和从磁盘配额
一.LVM概述 Logical Volume Manager,逻辑卷管理 优点:能够保证在现有数据不变的情况下,动态调整磁盘容量,从而提高磁盘管理的灵活性 /boot分区用于存放引导文件,不能基于LV ...
- 自然常数e的由来以及计算机为什么是二进制
背景 昨晚我在看一本书,叫<数学极客>,看到第六章<e:不自然的自然数>,这个数最早开始接触应该是高一的时候,那时候问老师,这个数是怎么来的,老实说,和圆周率一样,是一个常 ...
- 好用到爆!GitHub 星标 32.5k+的命令行软件管理神器,功能真心强大!
前言(废话) 本来打算在公司偷偷摸摸给星球的用户写一篇编程喵整合 MongoDB 的文章,结果在通过 brew 安装 MongoDB 的时候竟然报错了.原因很简单,公司这台 Mac 上的 homebr ...
- Qt数据可视化(散点图、折线图、柱状图、盒须图、饼状图、雷达图)开发实例
目录 散点图 折线图 柱状图 水平柱状图 水平堆叠图 水平百分比柱状图 盒须图 饼状图 雷达图 Qt散点图.折线图.柱状图.盒须图.饼状图.雷达图开发实例. 在开发过程中我们会使用多各种各样的图 ...