应用说明:
浏览文章会有很多的页码,就需要分页来实现,因为不可能把所有的页码放在文章列表的下面
一:实例准备:
1. models表结构为:
1 class Book(models.Model): 2 title=models.CharField(max_length=32) 3 price=models.DecimalField(max_digits=6,decimal_places=1)
2. 通过更高效的方式向数据库添加白条数据方法:
1 #批量导入数据,利用bulk_create效率会更高效 2 第一种:效率低 3 for i in range(100): 4 Book.objects.create(title="book"+str(i),price=i*4) 5 6 第二种:效率高 7 bookList=[] 8 for i in range(100): 9 book=Book(title="book"+str(i),price=i*4) 10 bookList.append(book) 11 12 Book.objects.bulk_create(bookList)
3. 分页的使用方法(views视图函数):
1 # 导入的模块 2 from .models import * 3 from django.core.paginator import Paginator,EmptyPage, PageNotAnInteger 4 5 # 分页器的用法 6 book_list = Book.objects.all() # 所有书籍对象 7 paginator = Paginator(book_list, 2) # 每页显示2个,所有方法都在paginator分页程序 8 9 # 分页器的三个属性 10 print("count:", paginator.count) # 数据总数 11 print("num_pages", paginator.num_pages) # 总页数 book_list/2 12 print("page_range", paginator.page_range) # 页码的列表() book_list 100 ,显示2个,这里就是(1,51) 13 14 # 获取前端传来的页码 get请求 15 pagenum = request.GET.get('page', 1) # 默认第一页,这里只是得到页码(注意是字符串) 16 17 # 获取第一页的对象 18 pagenum = int(pagenum) 19 page1 = paginator.page(pagenum) 20 21 # 如何获取当前页的数据对象,数据 22 for i in page1: # 遍历第1页的所有数据对象 23 print(i) 24 25 print(page1.object_list) # 第1页的所有数据,遍历 26 27 # 28 page2 = paginator.page(2) # 第二页的所有数据,遍历 29 30 # 上一页,下一页 31 print(page2.has_next()) # 是否有下一页 32 print(page2.next_page_number()) # 下一页的页码 33 print(page2.has_previous()) # 是否有上一页 34 print(page2.previous_page_number()) # 上一页的页码 35 36 # 抛错,注意报错的位置 37 # page=paginator.page(12) # error:EmptyPage 超出范围显示空 38 39 # page=paginator.page("z") # error:PageNotAnInteger 传入值错误
4. 前端页面渲染判断上一页或者下一页方法:
1 <ul class="pagination"> 2 3 {% if book_list.has_previous %} 4 <li><a href="/index/?page={{ book_list.previous_page_number }}" aria-label="Previous">上一页</a></li> 5 {% else %} 6 <li class="disabled"><a href="" aria-label="Previous">上一页</a></li> 7 {% endif %} 8 9 中间页码(1,2,3)内容 10 11 {% if book_list.has_next %} 12 <li><a href="/index/?page={{ book_list.next_page_number }}" aria-label="Next">下一页</a></li> 13 {% else %} 14 <li class="disabled"><a href="" aria-label="Next">下一页</a></li> 15 {% endif %} 16 17 </ul>
二:完整实际例子,注意前端循环的页码对象
创建Django项目,创建app01项目
1. urls代码:
1 from app01 import views 2 3 urlpatterns = [ 4 url(r'^admin/', admin.site.urls), 5 url(r'^index/', views.index), 6 ]
2. views视图函数代码:
1 def index(request): 2 book_list = Book.objects.all() # 全部对象 3 4 paginator = Paginator(book_list, 2) # 单页显示多少个 5 6 # currentPage = None 7 # pageRange = None 8 9 # try: # 异常处理,有可能用户通过url https://127.0.0.1:?page= 访问,需要对page=做处理 10 # global currentPage, pageRange 11 page = request.GET.get('page', 1) # 获取页码,默认1 12 print(type(page)) # 打印类型 int 类型 13 print(page) 14 15 # 处理访问路径的合法性,(解决抛错异常error:PageNotAnInteger 传入值错误) 16 if page == '0' or page == 1: 17 currentPage = 1 # 前端传来的是0,默认给第一页 18 elif page.isdigit(): 19 currentPage = int(page) # 前端传来数据页码,前端传过来字符串,需要转换 20 else: 21 currentPage = 1 # 前端传来的不是整数,默认给第一页 22 23 # 如果页码过多,使用,最后得到pageRange就是要显示的页码个数() 24 if paginator.num_pages > 10: # 总页码大于10,就不能让分页都显示出来了 25 26 if currentPage - 5 < 1: # 前端传来是小于6的页码,选中在左边 (第一页) 27 pageRange = range(1, 11) 28 elif currentPage > paginator.num_pages: # 前端传来的比总页还大,我应该给最后一页,并且要选中 (解决抛错异常error:EmptyPage 超出范围显示空) 29 pageRange = range(paginator.num_pages, paginator.num_pages + 1) # 最后一页,只有一个数 30 currentPage = paginator.num_pages 31 elif currentPage + 5 > paginator.num_pages: # 前端传来的加5大于总页,选中在右边 (最后一页) 32 pageRange = range(currentPage - 5, paginator.num_pages + 1) 33 else: 34 pageRange = range(currentPage - 5, currentPage + 5) # 传来的 中间页 35 36 else: 37 pageRange = paginator.page_range # 这个时候就不需要分页 38 print(pageRange) 39 40 try: 41 # 如果页码不大于10,也会有用户输入会超过的时候,这里就需要try 的抛错了 42 book_list = paginator.page(currentPage) # 获取第page页的对象,是这里抛错,就是判断前端返回,或者url直接访问的合法性 43 44 # except PageNotAnInteger: # 这里应该不需要异常的,上面在路径的合法性解决了 45 # book_list = paginator.page(1) # 传入的是错误的值,比如page是字母,特殊符号等,那就显示第一页的对象 46 # pageRange = range(1, 11) # 显示第一页内容,分页个数 1-10就可以 47 except EmptyPage: 48 book_list = paginator.page(paginator.num_pages) # 超出就显示最后一页的对象 49 currentPage = paginator.num_pages # 超出总页,需要重新给页码赋值一个最后页码 50 51 return render(request, "index.html", {'book_list': book_list, 'paginator': paginator, 'currentPage': currentPage, 'pageRange': pageRange})
3. index.html代码
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 <!-- 新 Bootstrap 核心 CSS 文件 --> 7 <link rel="stylesheet" href="//cdn.bootcss.com/bootstrap/3.3.5/css/bootstrap.min.css"> 8 </head> 9 <body> 10 11 12 <ul> 13 {% for book in book_list %} 14 <li>{{ book.title }}----------->{{ book.price }}</li> 15 {% endfor %} 16 17 </ul> 18 19 {#重点加这个pagination#} 20 <ul class="pagination"> 21 22 {% if book_list.has_previous %} 23 {# 重点Previous#} 24 <li><a href="/index/?page={{ book_list.previous_page_number }}" aria-label="Previous">上一页</a></li> 25 {% else %} 26 <li class="disabled"><a href="" aria-label="Previous">上一页</a></li> 27 {% endif %} 28 29 {% for pageNum in pageRange %} 30 {# 没有超出总页并且是选中的#} 31 {% if currentPage == pageNum %} 32 <li class="active"><a href="/index/?page={{ pageNum }}">{{ pageNum }}</a></li> 33 {# 超出总页码#} 34 {% elif currentPage > paginator.num_pages%} 35 <li class="active"><a href="/index/?page={{ paginator.num_pages }}">{{ paginator.num_pages }}</a></li> 36 {% else %} 37 {# 没有超出总页#} 38 <li><a href="/index/?page={{ pageNum }}">{{ pageNum }}</a></li> 39 {% endif %} 40 {% endfor %} 41 42 43 {% if book_list.has_next %} 44 {# 重点Next#} 45 <li><a href="/index/?page={{ book_list.next_page_number }}" aria-label="Next">下一页</a></li> 46 {% else %} 47 <li class="disabled"><a href="" aria-label="Next">下一页</a></li> 48 {% endif %} 49 </ul> 50 51 52 53 </body> 54 </html>
最后结果:
url http://127.0.0.1:8000/?page=
page后面是 字母,负数,0,其他字符 显示第一页分页
page后面是 整数 显示相应的分页
page后面是 整数 超过总页,显示最后一页
每页 十个页码