django_project_demo/app/utils/pagination.py

143 lines
5.9 KiB
Python
Raw Normal View History

2024-08-24 11:25:23 +08:00
"""
分页组件武沛奇视频课件讲解
"""
from django.utils.safestring import mark_safe
class Pagination(object):
def __init__(self, request, queryset, PAGE_SIZE=10, page_param='indexPage', PLUS_NAV=5):
"""
:param request: 视图函数,请求的对象
:param queryset: 传递过来的查询结果集,符合条件的记录
:param PAGE_SIZE: 每页显示记录数
:param page_param: 前端传递过来的页码 eg:/list/?indexPage=12
:param PLUS_NAV: 页码前后各几页
"""
# 为解决搜索后分页导航url地址丢失的问题
import copy
# 将url地址中所带的参数复制一份
query_dict = copy.deepcopy(request.GET)
# 允许修改
query_dict._mutable = True
self.query_dict = query_dict
self.page_param = page_param
page = request.GET.get(page_param, '1') # 当前页,默认第1页,如果是跳转的就读indexPage输入框内的值
if page.isdecimal(): # 判断page是否是一个数字
page = int(page)
else:
page = 1
self.page = page
self.page_size = PAGE_SIZE # 每页10条数据
self.star_page_data = (page - 1) * PAGE_SIZE # 开始数据
self.end_page_data = page * PAGE_SIZE # 结束数据
# star_page_data 开始记录数
# end_page_data 结束记录数
# [0:10] 取前10条数据
self.page_queryset = queryset[self.star_page_data:self.end_page_data]
# 统计共有多少条数据
# total_count_data 总记录数
total_count_data = queryset.count()
# 计算总页数 方法:通过总记录数和每页显示数相除
# divmod函数是python自带函数计算两数相除同时获得商和余数例如 divmod(91,10) 结果等于 {9,1}
# total_count_page总页数 mod就是余数
total_count_page, mod = divmod(total_count_data, PAGE_SIZE)
if mod:
total_count_page += 1 # 如果有余数总页数+1
self.total_count_page = total_count_page
self.plus_nav = PLUS_NAV
# 生成分页导航条
def html(self):
"""
生成分页导航条
计算出当前页前5页和后5页的页码
self.plus_nav 前后显示几页
star_page 起始页
end_page 结束页
total_count_page 总页数
page_nav 导航条的html代码
"""
# 计算导航栏页码数和显示方式(要考虑翻页时的极值)
# 效果是前5页和后5页 self.plus_nav
# 当数据量少比如只有100条数据以内则展示全部导航条
if self.total_count_page <= self.plus_nav * 2:
star_page = 1
end_page = self.total_count_page
else: # 大于100条数据时 显示前后5条数据
# 如果当前页小于5条极植
if self.page <= self.plus_nav:
star_page = 1
end_page = self.plus_nav * 2
else:
# 当前是每后一页时(极植)
if (self.page + self.plus_nav) >= self.total_count_page:
star_page = self.total_count_page - self.plus_nav * 2 # 显示前10页导航
end_page = self.total_count_page
else:
star_page = self.page - self.plus_nav
end_page = self.page + self.plus_nav
# 生成分页导航条的html代码并传递给前端
page_list = []
# 首页
# prev = '<li><a href="?page=1">首页</a></li>'
# 向url地址中拼接参数
self.query_dict.setlist(self.page_param, [1])
# 取得拼接后的url地址self.query_dict.urlencode()
prev = f'<li><a href="?{self.query_dict.urlencode()}" aria-label="Previous"><span aria-hidden="true">«</span></a></li>'
page_list.append(prev)
# 上一页
if self.page > 1:
self.query_dict.setlist(self.page_param, [self.page - 1])
prev = f'<li><a href="?{self.query_dict.urlencode()}">上一页</a></li>'
page_list.append(prev)
for i in range(star_page, end_page + 1): # range前取后不取所以+1
self.query_dict.setlist(self.page_param, [i])
if i == self.page:
ele = f'<li class="active"><a href="?{self.query_dict.urlencode()}">{i}</a></li>' # 给当前页加效果
else:
ele = f'<li><a href="?{self.query_dict.urlencode()}">{i}</a></li>'
page_list.append(ele)
# 下一页
if self.page < self.total_count_page:
self.query_dict.setlist(self.page_param, [self.page + 1])
prev = f'<li><a href="?{self.query_dict.urlencode()}">下一页</a></li>'
page_list.append(prev)
# 尾页
# prev = f'<li><a href="?page={total_count_page}">尾页</a></li>'
self.query_dict.setlist(self.page_param, [self.total_count_page])
prev = f'<li><a href="?{self.query_dict.urlencode()}" aria-label="Previous"><span aria-hidden="true">»</span></a></li>'
page_list.append(prev)
# 构建跳转html
page_nav_search = """
<li>
<form method="get" style="float: left;margin-left: -1px">
<input style="width: 100px;position: relative;float: left;display: inline-block;border-radius: 0" type="text" name="indexPage" class="form-control" placeholder="页码..">
<button style="border-radius: 0;" class="btn btn-default" type="submit">跳转</button>
</form>
</li>
"""
page_list.append(page_nav_search)
page_nav = ''.join(page_list)
# 因为page_nav是一个html字符串所以在传递到前端时要转换为安全的字符串
page_nav = mark_safe(page_nav)
"""分页实现结束"""
return page_nav