10. Django 分页器
作者:互联网
Django 分页器
版权声明:本博客来自路飞学城Python全栈开发培训课件,仅用于学习之用,严禁用于商业用途。
欢迎访问路飞学城官网:https://www.luffycity.com/
本节重点
- Django分页器相关类
- Django分页器的实现
- Django分页器的优化
1 Django分页器相关类
1.1 介绍
Django提供了一个内置类来帮助管理分页数据,这个模块存放在django.core.paginator.py。
其中有两个核心类,一个是Paginator类,另一个是Page类。
1.2 Paginator类
初始化源码:
class Paginator(object):
def __init__(self, object_list, per_page, orphans=0, allow_empty_first_page=True):
self.object_list = object_list
self.per_page = int(per_page)
self.orphans = int(orphans)
self.allow_empty_first_page = allow_empty_first_page
self._num_pages = self._count = None
类方法:
- Paginator.page(number):根据参数number返回一个Page对象。
类属型:
- Paginator.count:所有页面对象总数。
- Pagnator.num_pages:页面总数。
- pagiator.page_range:页面范围,从1开始,例如[1,2,3,4]。
1.3 Page类
初始化源码:
class Page(collections.Sequence):
def __init__(self, object_list, number, paginator):
self.object_list = object_list
self.number = number
self.paginator = paginator
类方法:
- Page.has_next() : 如果有下一页,则返回True。
- Page.has_previous() :如果有上一页,返回 True。
- Page.has_other_pages() :如果有上一页或下一页,返回True。
- Page.next_page_number() :返回下一页的页码。如果下一页不存在,抛出InvlidPage异常。
- Page.previous_page_number() :返回上一页的页码。如果上一页不存在,抛出InvalidPage异常。
- Page.start_index() :返回当前页上的第一个对象,相对于分页列表的所有对象的序号,从1开始。
比如,将五个对象的列表分为每页两个对象,第二页的start_index()会返回3。 - Page.end_index() :返回当前页上的最后一个对象,相对于分页列表的所有对象的序号,从1开始。
比如,将五个对象的列表分为每页两个对象,第二页的end_index() 会返回 4。
类属型:
- Page.object_list 当前页上所有对象的列表。
- Page.number 当前页的序号,从1开始。
- Page.paginator 相关的Paginator对象。
异常处理:
- InvalidPage(Exception):异常的基类(后两个异常都是InalidPage的子类),当paginator传入一个无效的页码时抛出。 Paginator.page()返回在所请求的页面无效(比如不是一个整数)时,或者不包含任何对象时抛出异常。
- exception PageNotAnInteger:当向page()提供一个不是整数的值时抛出。
- exception EmptyPage:当向page()提供一个有效值,但是那个页面上没有任何对象时抛出。
2. Django分页器的实现
views.py文件代码:
# views.py
from django.shortcuts import render,HttpResponse
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from app01.models import *
def index(request):
# 迭代all()时django会自动分块加载数据,并不会一次性加载所有数据到内存,可以放心遍历all()
# 但是仍然要注意大数据内存的使用,比如list(objects.all())此类操作
book_list=Book.objects.all() # 获取所有的book
paginator = Paginator(book_list, 10) # 每页10条
page = request.GET.get('page',1) # 获取页面请求的page页码,默认为第1页
currentPage=int(page)
try:
print(page)
book_list = paginator.page(page) # book_list为page对象
except PageNotAnInteger:
# If page is not an integer, deliver first page.
book_list = paginator.page(1) #
except EmptyPage:
# If page is out of range (e.g. 9999), deliver last page of results.
book_list = paginator.page(paginator.num_pages)
return render(request,"index.html",
{"book_list":book_list,"paginator":paginator,"currentPage":currentPage})
HTML文件代码:
# index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
</head>
<body>
<div class="container">
<h4>分页器</h4>
<ul>
{% for book in book_list %}
<li>{{ book.title }} -----{{ book.price }}</li>
{% endfor %}
</ul>
<ul class="pagination" id="pager">
{% if book_list.has_previous %}
<li class="previous">
<a href="/index/?page={{ book_list.previous_page_number }}">上一页</a>
</li>
{% else %}
<li class="previous disabled"><a href="#">上一页</a></li>
{% endif %}
{% for num in paginator.page_range %}
{% if num == currentPage %}
<li class="item active"><a href="/index/?page={{ num }}">{{ num }}</a></li>
{% else %}
<li class="item"><a href="/index/?page={{ num }}">{{ num }}</a></li>
{% endif %}
{% endfor %}
{% if book_list.has_next %}
<li class="next">
<a href="/index/?page={{ book_list.next_page_number }}">下一页</a>
</li>
{% else %}
<li class="next disabled"><a href="#">下一页</a></li>
{% endif %}
</ul>
</div>
</body>
</html>
以上,便实现了简单版的分页显示效果,若我们数据量很大时,会出现如下效果:
很显然,让所有的页签数都显示出来,不太合理,需要优化下。
3. Django分页器的优化
当页数实在太多时,我们不可能把所有的页数全部显示出来,比如固定显示7页,当点击“中间”一些页数的时候,两边固定显示前3页和后3页,改动如下:
views.py文件代码:
# views.py
from django.shortcuts import render,HttpResponse
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
from app01.models import *
def index(request):
book_list=Book.objects.all()
paginator = Paginator(book_list, 3)
page = request.GET.get('page',1)
currentPage=int(page)
if paginator.num_pages>7:
# 如果大于7,分情况处理
if currentPage-3<1:
pageRange=range(1,8)
elif currentPage+3>paginator.num_pages:
pageRange=range(currentPage-6,paginator.num_pages+1) #左开右闭
else:
pageRange=range(currentPage-3,currentPage+4)
else:
pageRange=paginator.page_range
try:
print(page)
book_list = paginator.page(page)
except PageNotAnInteger:
book_list = paginator.page(1)
except EmptyPage:
book_list = paginator.page(paginator.num_pages)
return render(request,"index.html",locals())
显示效果:
标签:paginator,10,num,分页,Page,list,Django,book,page 来源: https://blog.csdn.net/mannixiang/article/details/115676739