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 ...
随机推荐
- ngx_http_fastcgi_module 的那些事
是什么? 顾名思义,是Nginx用来处理FastCGI的模块.FastCGI是什么?这个以后再讲,可以说的是现在LNMP架构里面,PHP一般是以PHP-CGI的形式在运行,它就是一种FastCGI,我 ...
- golang的defer踩坑汇总
原文链接:http://www.zhoubotong.site/post/50.html defer语句用于延迟函数调用,每次会把一个函数压入栈中,函数返回前再把延迟的函数取出并执行.延迟函数可以有参 ...
- Linux基础命令、引号和括号的作用
查看硬件信息 查看 cpu lscpu命令可以查看cpu信息 cat /proc/cpuinfo也可看查看到 查看内存大小 free命令 cat /proc/meminfo 查看硬盘和分区 lsblk ...
- Python实现简繁体转换,真的玩得花
大家好鸭, 我是小熊猫 直接开搞!!! 1.opencc-python 首先介绍opencc中的Python实现库,它具有安装简单,翻译准确,使用方便等优点.对于我们日常的需求完全能够胜任. 1.1安 ...
- 到点了开始网抑云(悲)但是用python(整活)
写在前面的一点网抑云: 爱情不是随便许诺好了不想再说了没错 是我那么多的冷漠 让你感觉到无比的寂寞不过 一个女人的不仅仅渴望得到的一个承诺我害怕欺骗也害怕寂寞更害怕我的心会渐渐地凋落爱情不是随便许诺好 ...
- Linux修改默认ssh22端口
1.检查端口是否可用 使用下面的命令检查您想增加或修改的端口号是否被占用,执行命令后如果没有任何打印,说明这个端口没有被占用 netstat -lnp|grep 23456 2.修改配置文件 ssh配 ...
- scrapy框架入门
scrapy迄今为止依然是世界上最好用,最稳定的爬虫框架,相比于其他直接由函数定义的程序, scrapy使用了面向对象并对网页请求的过程分成了很多个模块和阶段,实现跨模块和包的使用,大大提升了代码的稳 ...
- go-zero微服务实战系列(十、分布式事务如何实现)
在分布式应用场景中,分布式事务问题是不可回避的,在目前流行的微服务场景下更是如此.比如在我们的商城系统中,下单操作涉及创建订单和库存扣减操作两个操作,而订单服务和商品服务是两个独立的微服务,因为每个微 ...
- Spring 核心概念
Spring 核心概念 引言 本文主要介绍 Spring 源码中使用到的一些核心类 1. BeanDefinition BeanDefinition表示Bean定义,BeanDefinition 中存 ...
- android studio取消设置代理
看标题感觉就是一个简单的设置,其实只是个大坑啊 https://www.jianshu.com/p/bb6d2bcdd5b5 android studio内虽然设置了 no proxy,但是没起作用, ...