参考博客:https://www.cnblogs.com/wupeiqi/articles/5246483.html
首先是路由这块,re_path 带的正则表达式应该这么写:
为了以后分页,路由带了数字的前期准备。
数量很多很多,这时候就需要分页。
可以获取 p 等于几,比如p=1 等于第一页, p=2等于第二页。
假设我们每页显示10条数据,那么:
接下来制作按钮,手动控制上一页与下一页
到目前为止,如果只是这种分页的功能,Django内置的分页组件就能够帮我们完成
如果要使用Django内置的分页功能,需要先引入一些东西:
然后:
然后前端:
接着看实现效果:
然后是上一页与下一页的设置:
可以看到分页这边写了很多分页代码,可以把这段代码单独保存起来,用的时候直接调用:
这里已经基本实现了分页与上一页跟下一页的功能了,接下来就是要实现带有数字的分页功能与点击数字调到指定页码。
但是Django自带的分页组件并没有这种功能,所以我们需要自己来实现。但是自己实现新功能,切记不要改源码,源码不能随便改,但是我们可以创建一个类,这个新创建的类可以继承 Paginator 这个类,然后通过这个新加的类来增加新功能。
然后前端页面显示页码的代码:
接着效果:
然后我们点击相对应的代码就能够跳转到相对应的页面。
但是效果还没有做好。我们让当前页面的样式要突出,非当前页面的样式则为普通,可以这么搞:
然后效果:
但是页码远不止这么点,而且页码数量不能写死,应该动态生成
由于创建了新类,就不使用原来的Django提供的类,而使用创建的新类:
然后继续往新类上添加功能(页码的动态生成):
由于新增了两个参数,所以下面这个地方也要改:
那么接下来就要计算总页数,如果页数少于11,不可能还显示11页。如果从第一页开始,不可能让第一页居中,以及最后11页同理。以下是相关代码:
效果图:
前面几页:
普通情况:
最后几页:
那么我们已经写好的这块代码,以后就可以单独保存起来,保存到一个py文件里,以后有需要使用可以直接拿来使用。
先来总结下扩展Django的分页功能:
然后自己要做的:
可以看到,区别在于这里只需要取出个数即可,可以通过计算,这一次只取多少到多少,然后再根据索引到数据库取数据即可。如果像Django那样直接取出数据,如果数据有一百万条,服务器就直接炸了。
那么为什么Django要这么做呢?
因为Django有个延迟加载,执行完 modle.xxxxx,并没有到数据库取数据,而是什么时候需要取数据才什么时候取。
首先我们创建一个 py 文件,在里面创建一个类,通过这个类来实现我们想要的功能:
然后效果:
可以看到,数据能出来了,接着制作上一页与下一页,制作之前先把前面已经弄好的代码可以放过来:
但是我们还少了一些东西,比如总页数,总页数需要计算,所以我们可以再添加计算页数的功能:
接着前端可以像前面一样:
虽然效果能够实现,但是这样跟Django自带的效果一样,于是决定换个方式:
然后结果:
因为Django的保护,这么用是生成不了的,需要加个 safe :
然后效果:
到此,基本就实现了,当然,上一页下一页还没实现:
首先改个地方:
然后:
然后效果:
到此要实现的效果就都实现了。当然我们还可以实现其它效果,比如首页尾页:
效果:
可能会有人觉得不好看,可以自行加样式,调整的更加好看。
到此,没有依赖Django的任何东西,就实现了分页的功能。
下面是总代码:
首先先看下 views 层调用的代码:
然后是前端代码:
然后是自定义分页功能的代码图:
自定义分页功能代码(可复制):
class Pagination(object):
def __init__(self,totalCount,currentPage,perPageItemNum = 30 , maxPageNum = 7):
self.totalCount = totalCount # 数据总个数
try: #异常处理,如果用户输入的页码有误,则直接将页码置于1
v = int(currentPage) # 当前页
if v <= 0 : # 作判断,如果输入例如 -1 这种
v = 1
self.current_page = v
except Exception as e:
self.current_page = 1
self.perPageItemNum = perPageItemNum # 每页显示的行数
self.maxPageNum = maxPageNum # 最多显示多少页码
def start(self): # 页码对应的起始数据
return (self.current_page - 1) * self.perPageItemNum
def end(self): # 页码对应的结尾数据
return self.current_page * self.perPageItemNum
@property #把方法伪造成属性,如果不加这个,下面用到这个方法都要加括号
def num_pages(self):
# 可以用py的内置函数 divmod ,输入被除数与除数,可以得到商跟余数
a,b = divmod(self.totalCount,self.perPageItemNum) # a是商,b是余数
if b == 0:
return a
return a+1
def pager_num_range(self): #显示页码,这里是1到11
# 当前页 self.current_page
# 最多显示的页码数量11 self.perPageItemNum
# 总页数 self.num_pages
if self.num_pages < self.maxPageNum: # 如果总页数少于要显示的11页,则只输出这么点页数
return range(1,self.num_pages+1)
part = int(self.maxPageNum/2) # 取11的中间页码,让当前页码始终处于中间状态,前后都有页码可以点击
if self.current_page <= part: #这里处理从第一页开始时,页码的显示情况
return range(1,self.maxPageNum+1) # 如果当前页小于6,则显示页码数量为1到11
if (self.current_page + part) > self.num_pages: #这里处理页码处于最后的11页的时候
return range(self.num_pages - self.maxPageNum + 1 , self.num_pages + 1) #当前页处于最后的11页时,直接显示最后的11页
return range(self.current_page - part ,self.current_page + part + 1) # 当前页居中时,前面显示5条页码,后面显示5条页码
def page_str(self):
page_list = []
first = " 首页 "
page_list.append(first)
if self.current_page == 1: # 如果为第一页,则点击上一页无效果
prev = " 上一页 "
else:
prev = " 上一页 " %(self.current_page - 1,)
page_list.append(prev) #把上一页的标签放到数组中
for i in self.pager_num_range():
if i == self.current_page:
temp = " %s " %(i,i) #动态生成前端标签
else:
temp = " %s " % (i, i)
page_list.append(temp)
if self.current_page == self.num_pages: # 如果页码为最后一页,则点击下一页无效果
nex = " 下一页 "
else:
nex = " 下一页 " %(self.current_page + 1,)
page_list.append(nex) #把下一页的标签放到数组中
last = " 尾页 " %(self.num_pages,)
page_list.append(last)
return ''.join(page_list)