Django 分页器 Paginator
分页器要导入的包
from django.core.paginator import Paginator
Paginator 就是分页器导入的模块
from django.core.paginator import EmptyPage
EmptyPage 是一个错误异常,用于超出页数范围外而抛出的异常
分页器的常用方法
paginator = Paginator(bks, 7) #Paginator 添加所有返回的数据对象,和每页展示多少数据的int参数
paginator.count # 数据页数
paginator.num_pages # 按照上面7条数据分后的总页数
paginator.page_range # 页码的列表
-----------------------------------------------------------------------------
page1 = paginator.page(1) # 获取第一页的数据对象
for i in page1: #遍历page1的所有数据,效果和 object_list 一样,只不过object_list是列表形式
print(i)
page1.object_list #page1的所有数据 列表形式
--------------------------------------------------------------------------------
page1.has_next() #是否有下一页
page1.has_other_pages() #是否有下一页或者上一页
page1.has_previous() #是否有上一页
page1.next_page_number() #获取下一页页码 和 has_next一起用
page1.previous_page_number() #获取下一页页码 和 has_previous一起用
用分页器分页显示数据的数据
先利用models.object.bulk_create()进行批量插入数据
bk_list=[]
for i in range(1,100):
bk = models.test.objects.create(name="python-%i"%(i),price=i,)
bk_list.append(bk)
try:
#不用try会提示primary_key重复,不知道原因在哪里,数据可以正常插入
models.test.objects.bulk_create(bk_list)
except Exception:
pass
效果图
分页展示数据
用分页器展示下面的选择页数
效果图
用分页器展示下面的选择页数添加选中的页数底色添加效果
给选中的当前页数添加class ="active"就行.
效果图
用分页器对于上一页 下一页的条件设定
对于上一页 下一页 要实现 分别会进行页数加减,但是也要实现第一页的时候点击上一页无效,最后一页的时候点击下一页无效
页数加减,可以用蒙版语法的过滤器add实现 上一页就add:-1,下一页就add:1,也可以使用当前页的对象的next_page_number 和previous_page_number方法
用分页器只展示11页数据,其他多余的隐藏动态显示
效果展示
大致思路如下:
获取总页数:paginator.num_pages
假设当前页是current_page,总页数是total_page
如果当前点击页数是1,那么就显示1-11页,页数直接返回一个range(1,12)
如果当前点击页数是最后一页,那么就返回区间range(total_page-11,total_page+1)
如果点击的是中间的页数,返回区间(current_page-5,current_page+6)
这里还要考虑2个情况 如果current_page-5<1的时候和current_page+6>total_page的时候.
自定义实现的分页器
django内置分页器功能不是很强大.下面是一个封装的分页器,可以搭配form组件进行使用
视图函数
def customer_list(request):
# 所有数据
queryset = models.Customer.objects.filter(active=1).select_related('level')
pager = Pagination(request, queryset)
context = {
"queryset": queryset[pager.start:pager.end],
"pager_string": obj.html()
}
return render(request, 'customer_list.html', context)
HTML代码
{% for obj in queryset %}
<tr>
<td>{{ obj.id }}</td>
<td>{{ obj.username }}</td>
<td>{{ obj.mobile }} </td>
<td>{{ obj.level.title }} </td>
<td>{{ obj.get_role_level_display }} </td>
<td><a class="btn btn-primary" href="{% url 'customer_edit' obj.id %}">编辑</a></td>
<td><a class="btn btn-danger del_btn" idx="{{ obj.id }}">删除</a></td>
</tr>
{% endfor %}
<ul class="pagination">
{{ pager_string }}
</ul>
封装的分页器
关于self.query_dict.setlist,self.query_dict._mutable = True 看下面
https://www.cnblogs.com/Young-shi/p/15085527.html
里的视图请求
如果想要以后使用分页,需要以下两个步骤:
在视图函数:
def customer_list(request):
# 所有数据
queryset = models.Customer.objects.filter(active=1).select_related('level')
pager = Pagination(request, queryset)
context = {
"queryset": queryset[pager.start:pager.end],
"pager_string": obj.html()
}
return render(request, 'customer_list.html', context)
在页面上:
{% for row in queryset %}
{{row.id}}
{% endfor %}
<ul class="pagination">
{{ pager_string }}
</ul>
import copy
from django.utils.safestring import mark_safe
class Pagination(object):
""" 分页 """
def __init__(self, request, query_set, per_page_count=10):
self.query_dict = copy.deepcopy(request.GET)
self.query_dict._mutable = True
self.query_set = query_set
total_count = query_set.count()
self.total_count = total_count
# 计算出总共有多少页面
self.total_page, div = divmod(total_count, per_page_count)
if div:
self.total_page += 1
page = request.GET.get('page')
if not page:
page = 1
else:
if not page.isdecimal():
page = 1
else:
page = int(page)
if page <= 0:
page = 1
else:
if page > self.total_page:
page = self.total_page
# 封装计算分多少页
self.page = page
self.per_page_count = per_page_count
self.start = (page - 1) * per_page_count
self.end = page * per_page_count
def html(self):
pager_list = []
if not self.total_page:
return ""
# 总页码小于11
if self.total_page <= 11:
start_page = 1
end_page = self.total_page
else:
# 总页码比较多
# 判断当前页 <=6: 1~11
if self.page <= 6:
start_page = 1
end_page = 11
else:
if (self.page + 5) > self.total_page:
start_page = self.total_page - 10
end_page = self.total_page
else:
start_page = self.page - 5
end_page = self.page + 5
self.query_dict.setlist('page', [1])
pager_list.append('<li><a href="?{}">首页</a></li>'.format(self.query_dict.urlencode()))
# 设置上一页标签
if self.page > 1:
self.query_dict.setlist('page', [self.page - 1])
pager_list.append('<li><a href="?{}">上一页</a></li>'.format(self.query_dict.urlencode()))
# 遍历产生标签
for i in range(start_page, end_page + 1):
self.query_dict.setlist('page', [i])
if i == self.page:
item = '<li class="active"><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
else:
item = '<li><a href="?{}">{}</a></li>'.format(self.query_dict.urlencode(), i)
pager_list.append(item)
# 设置下一页标签
if self.page < self.total_page:
self.query_dict.setlist('page', [self.page + 1])
pager_list.append('<li><a href="?{}">下一页</a></li>'.format(self.query_dict.urlencode()))
#设置 尾页
self.query_dict.setlist('page', [self.total_page])
pager_list.append('<li><a href="?{}">尾页</a></li>'.format(self.query_dict.urlencode()))
pager_list.append('<li class="disabled"><a>数据{}条{}页</a></li>'.format(self.total_count, self.total_page))
pager_string = mark_safe("".join(pager_list))
return pager_string
def queryset(self):
if self.total_count:
return self.query_set[self.start:self.end]
return self.query_set