九:django分页器
自定义分页器的实现
前言
django也有自带额分页器,但是功能较少,使用起来较为繁琐。所以我们可以使用自定义非分页器。
自定义分页器的推导思路
# queryset对象是支持索引切片操作的(不支持负数索引)
book_queryset=models.Book.objects.all()
page_queryset=book_queryset[page_obj.start:page_obj.end]
# 如何获取用户访问的页数?
get请求是可以携带参数:url?page
默认显示的是第一页:current_page=request.GET.get("page",1)
"page"参数非法,则显示默认的第一页
# 设定每页的展示的记录数?
per_page_num=10
# 切片的起始位置和结束位置
start_page=(current_page-1)*10
end_page=current_page*10
# 获取展示数据的总条数
record_count=book_queryset.count() //通过queryset对象的count方法获取数据库数据的总条数
# 确定总的数据需要多少页才能展示
内置方法divmod()
base_page,is_carry=divmod(record_count,per_page_num)
# 前端模板语法没有range功能
前端代码后端书写,写完传给前端
# 针对展示页码的需要自己规划好到底展示多少个页码
一般情况下页码的个数设计都是奇数(符合审美标准) 11个页码
当前页减5
当前页加6
你可以给标签价样式从而让选中的页码高亮显示
# 针对页码小于6的情况 你需要做处理 不能再减
思路有了,那就撸起袖子写吧。
封装好的代码
"""
自定义分页器代码
"""
class Pager(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)
使用
注意:
"""
当我们需要使用到非django内置的第三方功能或者组件代码的时候,一般情况下会创建一个名为utils文件夹,在该文件夹内对模块进行功能性划分,utils可以在每个应用下创建,需要具体结合实际情况。
我们自定义的分页器是基于bootstrap样式来的,所以你需要提前导入bootstrap:
(1)bootstrap 版本 v3
(2)jQuery 版本 v3
"""
└── utils
├── pager.py
└── __pycache__
└── pager.cpython-38.pyc
django后端:
class Book(View):
def get(self, request, phone):
user_obj = models.User.objects.filter(phone=phone).first()
book_list = models.Book.objects.all()
current_page = request.GET.get("page", 1)
record_count = book_list.count()
page_obj = pager.Pager(current_page, record_count, per_page_num=7, pager_count=11)
page_queryset = book_list[page_obj.start:page_obj.end]
return render(request, 'book.html',
{'user': user_obj, 'page': page_obj, 'page_queryset': page_queryset})
前端:
<div class="col-lg-6">
<div class="input-group">
<input type="text" class="form-control" placeholder="书名~">
<span class="input-group-btn">
<button class="btn btn-success" type="button">搜索~</button>
</span>
</div><!-- /input-group -->
</div>
<div class="col-lg-6 text-right">
<a href="{% url 'app01:book_add' user.phone %}" class="btn btn-success">添加书籍</a>
</div><br><br><br>
<div class="col-lg-10 col-lg-offset-1">
<table class="table table-bordered table-striped table-hover">
<thead>
<tr>
<th class="text-center thead-style">序号</th>
<th class="text-center thead-style">书名</th>
<th class="text-center thead-style">价格(元)</th>
<th class="text-center thead-style">作者</th>
<th class="text-center thead-style">出版日期</th>
<th class="text-center thead-style">出版社</th>
<th class="text-center thead-style">操作</th>
</tr>
</thead>
<tbody>
{% for book in page_queryset %}
<tr>
<td class="text-center tbody-style">{{ page.start|add:forloop.counter }}</td>
<td>{{ book.name }}</td>
<td class="text-center">{{ book.price }}</td>
<td>
{% for author in book.authors.all %}
{% if forloop.last %}
{{ author.name }}
{% else %}
{{ author.name }}|
{% endif %}
{% endfor %}
</td>
<td class="text-right">{{ book.publish_date|date:'Y/m/d' }}</td>
<td class="text-center">{{ book.publish.name }}</td>
<td class="text-center">
<a href="{% url 'app01:book_edit' user.phone book.id %}"
class="btn btn-primary btn-xs">编辑</a>
<button class="btn btn-danger btn-xs del" delete_id="{{ book.pk }}">删除</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
<div class="text-center">
{{ page.page_html|safe }}
</div>
</div>