利用django自带分页组件实现分页功能
使用分页器Paginator:
在视图中使用 Paginator来为查询集分页。我们提供视图以及相关的模板来展示如何展示这些结果。
Paginator常用属性 per_page: 每页显示条目数量 count: 数据总个数 num_pages:总页数 page_range:总页数的索引范围,页码的范围,从1开始,例如[1, 2, 3, 4]
Paginator所需参数:
object_list 一个列表,元祖或则Django 的Queryset 对象 或其他对象带有 count() or __len__()的方法 per_page :就是1页显示几条数据
Paginator对象的方法:
page(number) :返回在提供的下标处的Page对象,下标以1开始
使用page对象方法:
Page.has_next() 如果有下一页,则返回True Page.has_previous() 如果有上一页,返回 True Page.has_other_pages() 如果有上一页或下一页,返回True Page.next_page_number() 返回下一页的页码。如果下一页不存在,抛出InvalidPage异常 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对象。
自带分页功能代码
1 """fbv_cbv URL Configuration 2 3 The `urlpatterns` list routes URLs to views. For more information please see: 4 https://docs.djangoproject.com/en/2.1/topics/http/urls/ 5 Examples: 6 Function views 7 1. Add an import: from my_app import views 8 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 Class-based views 10 1. Add an import: from other_app.views import Home 11 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 Including another URLconf 13 1. Import the include() function: from django.urls import include, path 14 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 """ 16 from django.contrib import admin 17 from django.urls import path, re_path 18 from app01 import views 19 20 urlpatterns = [ 21 path('admin/', admin.site.urls), 22 path('index/', views.index), # 自带分页 23 ]
1 from django.db import models 2 3 4 class UserType(models.Model): 5 title = models.CharField(max_length=32) 6 7 8 class UserInfo(models.Model): 9 username = models.CharField(max_length=32) 10 password = models.CharField(max_length=64) 11 age = models.IntegerField() 12 ut = models.ForeignKey('UserType', on_delete=models.CASCADE) 13 14 def __str__(self): 15 return '%s--%s' % (self.id, self.username)
1 from django.shortcuts import render, HttpResponse 2 from django.core.paginator import Paginator, Page, PageNotAnInteger, EmptyPage 3 from app01 import models 4 5 6 def index(request): 7 """ 8 Django自带的分页功能 局限性:不能在其他框架中用 而且只能做到上一页 下一页的位置 9 :param request: 10 :return: 11 """ 12 13 # for i in range(300): 14 # username = "root" + str(i) 15 # models.UserInfo.objects.create(username=username, age=18, ut_id=1) 16 current_page = request.GET.get('page') 17 user_list = models.UserInfo.objects.all() 18 paginator = Paginator(user_list, 10) 19 # per_page: 每页显示条目数量10 20 # count: 数据总个数 21 # num_pages:总页数 22 # page_range:总页数的索引范围,如: (1,10),(1,200) 23 # page: page对象 24 try: 25 posts = paginator.page(current_page) 26 except PageNotAnInteger as e: 27 posts = paginator.page(1) 28 except EmptyPage as e: # 传入负数异常 29 posts = paginator.page(1) 30 # has_next 是否有下一页 31 # next_page_number 下一页页码 32 # has_previous 是否有上一页 33 # previous_page_number 上一页页码 34 # object_list 分页之后的数据列表 35 # number 当前页 36 # paginator paginator对象 37 return render(request, 'index.html', {"posts": posts})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> </head> <body> <h2>用户列表数据</h2> <ul> {% for row in posts.object_list %} <li>{{ row.username }}</li> {% endfor %} </ul> <div> {% if posts.has_previous %} <a href="?page={{ posts.previous_page_number }}">上一页</a> {% endif %} {% for num in posts.paginator.page_range %} <a href="?page={{ num }}">{{ num }}</a> {% endfor %} {% if posts.has_next %} <a href="?page={{ posts.next_page_number }}">下一页</a> {% endif %} </div> </body> </html>
自带分页实现的效果
总结下自带的分页:1.局限性太强,不能在其它框架中用2.只能做到上一页下一页位置3.如果数据库数据非常多,页码全部展示在一个页面肯定是不好的
自定义分页功能
实现主要思想:1.创建一个类,封装用户传递的页码、统计数据库总的个数、每页显示的数据条数、展示的页码数量、基本的url路径
2.在类中实现当前页面的起始位置数据
3.在页面上展示的页码条数以及上页下页(处理上页下页逻辑多做出判断)
1 """fbv_cbv URL Configuration 2 3 The `urlpatterns` list routes URLs to views. For more information please see: 4 https://docs.djangoproject.com/en/2.1/topics/http/urls/ 5 Examples: 6 Function views 7 1. Add an import: from my_app import views 8 2. Add a URL to urlpatterns: path('', views.home, name='home') 9 Class-based views 10 1. Add an import: from other_app.views import Home 11 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') 12 Including another URLconf 13 1. Import the include() function: from django.urls import include, path 14 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) 15 """ 16 from django.contrib import admin 17 from django.urls import path, re_path 18 from app01 import views 19 20 urlpatterns = [ 21 path('admin/', admin.site.urls), 22 path('custom/', views.custom), # 自定义分页 23 ]
1 from django.shortcuts import render, HttpResponse 2 from django.core.paginator import Paginator, Page, PageNotAnInteger, EmptyPage 3 from app01 import models 4 5 6 class PageInfo(object): 7 def __init__(self, current_page, all_count, per_page, base_url, show_page=11): 8 """ 9 10 :param current_page: 当前用户传递的页码 11 :param all_count: 数据库总的多少条个数 12 :param per_page: 每页显示的数据条数 13 :param show_page: 看到页码的最大值 前5条加后5条+当前页 14 :param base_url: url路径 15 """ 16 try: 17 self.current_page = int(current_page) 18 except Exception as e: 19 self.current_page = 1 20 self.per_page = per_page 21 22 a, b = divmod(all_count, per_page) 23 if b: 24 a = a + 1 25 self.all_pager = a 26 self.show_page = show_page 27 self.base_url = base_url 28 29 def start(self): 30 return (self.current_page-1)*self.per_page 31 32 def end(self): 33 return self.current_page*self.per_page 34 35 def pager(self): 36 # v = "<a href='/custom/?page=6'>6</a>" 37 # return v 38 page_list = [] 39 # 调整起始位置就可以在当前页码前几个显示出来后几页显示出来 40 harf = int((self.show_page-1)/2) # 5 41 # begin = self.current_page - harf 42 # stop = self.current_page + harf + 1 43 # 判断起始 结束 加中间页码的逻辑 44 # 如果数据总页数小于11(默认页码显示的最大值) 45 if self.all_pager < self.show_page: 46 begin = 1 47 stop = self.all_pager + 1 48 # 如果数据总页数大于11(默认页码显示的最大值) 49 else: 50 # 如果当前页<=5 就永远显示1,11页 51 if self.current_page <= harf: 52 begin = 1 53 stop = self.show_page + 1 54 else: 55 # 这里注意 如果后边没数据浏览的页码大于全部页码时候也要进行处理 56 if self.current_page + harf > self.all_pager: 57 begin = self.all_pager - self.show_page + 1 58 stop = self.all_pager + 1 59 else: 60 begin = self.current_page - harf 61 stop = self.current_page + harf + 1 62 63 # begin = self.current_page - 5 64 # stop = self.current_page + 5 + 1 65 if self.current_page <= 1: 66 prev = "<li><a href='#'>上一页</a></li>" 67 else: 68 prev = "<li><a href='%s?page=%s'>上一页</a></li>" % (self.base_url, self.current_page - 1) 69 page_list.append(prev) 70 71 for i in range(begin, stop): 72 if i == self.current_page: 73 temp = "<li class='active'><a href='%s?page=%s'>%s</a></li>" % (self.base_url, i, i,) 74 else: 75 temp = "<li><a href='%s?page=%s'>%s</a></li>" % (self.base_url, i, i,) 76 page_list.append(temp) 77 78 if self.current_page >= self.all_pager: 79 nex = "<li><a href='#'>下一页</a></li>" 80 else: 81 nex = "<li><a href='%s?page=%s'>下一页</a></li>" % (self.base_url, self.current_page + 1) 82 page_list.append(nex) 83 84 return ''.join(page_list) 85 86 87 def custom(request): 88 """ 89 自定义分页 90 :param request: 91 :return: 92 """ 93 # 假设当前页为第5页 94 current_page = request.GET.get('page') 95 all_count = models.UserInfo.objects.all().count() 96 # current_page = int(current_page) 97 # 每页显示的数据个数 98 per_page = 10 99 # 1 [0 10] 100 # 2 [10 20] 101 # 3 [20 30] 102 page_info = PageInfo(current_page, all_count, per_page, '/custom/', 11) 103 # start = (current_page-1)*per_page 104 # end = current_page*per_page 105 # user_list = models.UserInfo.objects.all()[开始位置:结束位置] 106 user_list = models.UserInfo.objects.all()[page_info.start(): page_info.end()] 107 108 return render(request, "custom.html", {"user_list": user_list, "page_info": page_info})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title></title> <link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.css"> </head> <body> <h2>用户列表数据</h2> <ul> {% for row in user_list %} <li>{{ row.username }}</li> {% endfor %} </ul> <nav aria-label="Page navigation"> <ul class="pagination"> {{ page_info.pager | safe }} </ul> </nav> </body> </html>
静态文件的加载就不上传了 下载下来用就是了
自带分页器+自定义分页目录
数据少时,大于总页数就没数据了的处理 处理默认显示的总的页码(11页)的问题 数据少显示出来的负数页面