02-分页器,自定义分页器,解耦函数分页器,分页器class
1 、批量数据导入
主url
from django.contrib import admin from django.urls import path, re_path, include urlpatterns = [ path('admin/', admin.site.urls), re_path(r'app01/', include(('app01.urls', 'app01'))) ]
urls
from django.urls import path, re_path, include from app01 import views urlpatterns = [ re_path(r'^index/$', views.index, name='index') ]
modles
from django.db import models class Book(models.Model): id = models.AutoField(primary_key=True) title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2)
数据库迁移
C:\PycharmProjects\pagedemo>python manage.py makemigrations C:\PycharmProjects\pagedemo>python manage.py migrate
views:批量生成数据
from django.shortcuts import render from app01.models import Book def index(request): # 添加100条书籍数据 # 方式1: for i in range(100): Book.objects.create(title='book_%s' % i, price=i*i) # 方式2:生成100个实例对象,创建效率高 book_list = [] for i in range(100): book_obj = Book(title="book_%s" % i, price=i*i) book_list.append(book_obj) Book.objects.bulk_create(book_list) # 批量导入 return render(request, 'index.html')
views,前台显示所有的book_list
from django.shortcuts import render from app01.models import Book def index(request): book_list = Book.objects.all() return render(request, 'index.html', locals())
templates 模板层
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for book in book_list %} <li>{{ book.title }} : {{ book.price }}</li> {% endfor %} </ul> </body> </html>
2、分页器的使用
from django.core.paginator import Paginator # 分页器
1、对谁做分页, 每页几条数据
# 1.对谁做分页, 每页几条数据 paginator = Paginator(book_list, 12) # 对book_list数据分页,每页10条数据 print('count:', paginator.count) # 数据总个数 100 print('num_page:', paginator.num_pages) # 总页数 9 print('per_page', paginator.per_page) # 每页显示条目数量 12 print('page_range', paginator.page_range) # 页码的列表 range(1, 10) print('page', paginator.page) # page对象 <django.core.paginator.Paginator object at 0x0412EAF0>
2.显示某一页的具体数据的两种方法
# 方式1:固定页码num page1 = paginator.page(1) # 获取第1页的page对象 print("object_list", page1.object_list) # page的object_list属性 for item in page1: # for打印每条数据对象 print(item) # 方式2:动态获取当前页码num print(request.GET) # http://127.0.0.1:8000/app01/index/?page=1 current_page_num = int(request.GET.get("page")) # 1 <QueryDict: {'page': ['2']}> current_page = paginator.page(current_page_num) # 当前num页码的page对象
3、模板层显示数据
<ul> {% for book in current_page %} <li>{{ book.title }} : {{ book.price }}</li> {% endfor %} </ul>
4、超过page范围,异常捕获
from django.core.paginator import Paginator, EmptyPage # 分页器 try: print(request.GET) # http://127.0.0.1:8000/app01/index/?page=1 current_page_num = int(request.GET.get("page", '1')) # 1 # <QueryDict: {'page': ['2']}> current_page = paginator.page(current_page_num) except EmptyPage as e: current_page = paginator.page(1) except ValueError as e: current_page = paginator.page(1)
5、代码
views视图
from django.shortcuts import render from app01.models import Book from django.core.paginator import Paginator, EmptyPage # 分页器 def index(request): # 添加100条书籍数据 # 方式1: for i in range(100): Book.objects.create(title='book_%s' % i, price=i*i) # 方式2:生成100个实例对象,创建效率高 book_list = [] for i in range(100): book_obj = Book(title="book_%s" % i, price=i*i) book_list.append(book_obj) Book.objects.bulk_create(book_list) # 批量导入 book_list = Book.objects.all() # 分页器的使用 # 1.对谁做分页, 每页几条数据 paginator = Paginator(book_list, 12) # 对book_list数据分页,每页12条数据 print('count:', paginator.count) # 数据总个数 100 print('num_page:', paginator.num_pages) # 总页数 9 print('per_page', paginator.per_page) # 每页显示条目数量 12 print('page_range', paginator.page_range) # 页码的列表 range(1, 10) print('page', paginator.page) # page对象 <django.core.paginator.Paginator object at 0x0412EAF0> # 2.显示某一页的具体数据的两种方法 # 方式1:固定页码num page1 = paginator.page(1) # 获取第1页的page对象 print("object_list", page1.object_list) # page的object_list属性 for item in page1: # for打印每条数据对象 print(item) # 方式2:动态获取当前页码num try: print(request.GET) # http://127.0.0.1:8000/app01/index/?page=1 current_page_num = int(request.GET.get("page", '1')) # 1 # <QueryDict: {'page': ['2']}> current_page = paginator.page(current_page_num) except EmptyPage as e: current_page = paginator.page(1) except ValueError as e: current_page = paginator.page(1) return render(request, 'index.html', locals())
模板层
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for book in current_page %} <li>{{ book.title }} : {{ book.price }}</li> {% endfor %} </ul> </body> </html>
3、bootstrap页码
1、配置
<!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> <!-- 可选的 Bootstrap 主题文件(一般不用引入) --> <link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" integrity="sha384-rHyoN1iRsVXV4nD0JutlnGaslCJuC7uwjduW9SVrLvRYooPp2bWYgmgJQIXwl/Sp" crossorigin="anonymous"> <!-- 最新的 Bootstrap 核心 JavaScript 文件 --> <script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<nav aria-label="Page navigation"> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> <li><a href="#">1</a></li> <li><a href="#">2</a></li> <li><a href="#">3</a></li> <li><a href="#">4</a></li> <li><a href="#">5</a></li> <li> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </nav>
2、正常页码显示
<nav aria-label="Page navigation"> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">上一页</span> </a> </li> {% for item in paginator.page_range %} <li><a href="?page={{ item }}">{{ item }}</a></li> {% endfor %} <li> <a href="#" aria-label="Next"> <span aria-hidden="true">下一页</span> </a> </li> </ul> </nav>
3、页码点击,active
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <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> <ul> {% for book in current_page %} <li>{{ book.title }} : {{ book.price }}</li> {% endfor %} </ul> <nav aria-label="Page navigation"> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">上一页</span> </a> </li> {% for item in paginator.page_range %} {% if item == current_page_num %} <li class="active"><a href="?page={{ item }}">{{ item }}</a></li> {% else %} <li><a href="?page={{ item }}">{{ item }}</a></li> {% endif %} {% endfor %} <li> <a href="#" aria-label="Next"> <span aria-hidden="true">下一页</span> </a> </li> </ul> </nav> </body> </html>
4、上一页,下一页
设置add+1 add-1
bug:页码超出限制,出现bug
view视图代码
# 4.上一页,下一页 try: print(current_page.has_previous()) # 是否有上一页 print(current_page.previous_page_number()) # 上一页的页码 print(current_page.has_next()) # 是否有下一页 print(current_page.next_page_number()) # 下一页的页码 except EmptyPage as e: pass
from django.shortcuts import render from app01.models import Book from django.core.paginator import Paginator, EmptyPage # 分页器 def index(request): # 添加100条书籍数据 # 方式1: # for i in range(100): # Book.objects.create(title='book_%s' % i, price=i*i) # 方式2:生成100个实例对象,创建效率高 # book_list = [] # for i in range(100): # book_obj = Book(title="book_%s" % i, price=i*i) # book_list.append(book_obj) # # Book.objects.bulk_create(book_list) # 批量导入 # book_list = Book.objects.all() # 分页器的使用 # 1.对谁做分页, 每页几条数据 paginator = Paginator(book_list, 12) # 对book_list数据分页,每页10条数据 print('count:', paginator.count) # 数据总个数 100 print('num_page:', paginator.num_pages) # 总页数 9 print('per_page', paginator.per_page) # 每页显示条目数量 12 print('page_range', paginator.page_range) # 页码的列表 range(1, 10) print('page', paginator.page) # page对象 <django.core.paginator.Paginator object at 0x0412EAF0> # 2.显示某一页的具体数据的两种方法 # 方式1:固定页码num page1 = paginator.page(1) # 获取第1页的page对象 print("object_list", page1.object_list) # page的object_list属性 for item in page1: # for打印每条数据对象 print(item) # 方式2:动态获取当前页码num # print(request.GET) # http://127.0.0.1:8000/app01/index/?page=1 # current_page_num = int(request.GET.get("page", '1')) # 1 # <QueryDict: {'page': ['2']}> # current_page = paginator.page(current_page_num) # 3.抛出Empty异常 try: print(request.GET) # http://127.0.0.1:8000/app01/index/?page=1 current_page_num = int(request.GET.get("page", '1')) # 1 # <QueryDict: {'page': ['2']}> current_page = paginator.page(current_page_num) except EmptyPage as e: current_page = paginator.page(1) except ValueError as e: current_page = paginator.page(1) # 4.上一页,下一页 try: print(current_page.has_previous()) # 是否有上一页 print(current_page.previous_page_number()) # 上一页的页码 print(current_page.has_next()) # 是否有下一页 print(current_page.next_page_number()) # 下一页的页码 except EmptyPage as e: pass """ if 当前page对象有 上一页 <a href="?page={{ current_page.previous_page_number }}"> else: <a href=""> """ return render(request, 'index.html', locals())
模板层:
伪代码实现:
if 当前page对象有 上一页 <a href="?page={{ current_page.previous_page_number }}"> else: <a href="">
# 上一页 {% if current_page.has_previous %} <li> <a href="?page={{ current_page.previous_page_number }}" aria-label="Previous"><span aria-hidden="true">上一页</span></a> </li> {% else %} <li class="disabled"> <a href="" aria-label="Previous"><span aria-hidden="true">上一页</span></a> </li> {% endif %} # 下一页 {% if current_page.has_next %} <li> <a href="?page={{ current_page.next_page_number }}" aria-label="Next"><span aria-hidden="true">下一页</span></a> </li> {% else %} <li class="disabled"> <a href="" aria-label="Next"><span aria-hidden="true">下一页</span></a> </li> {% endif %}
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <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> <ul> {% for book in current_page %} <li>{{ book.title }} : {{ book.price }}</li> {% endfor %} </ul> <nav aria-label="Page navigation"> <ul class="pagination"> {# 上一页#} {% if current_page.has_previous %} <li> <a href="?page={{ current_page.previous_page_number }}" aria-label="Previous"><span aria-hidden="true">上一页</span></a> </li> {% else %} <li class="disabled"> <a href="" aria-label="Previous"><span aria-hidden="true">上一页</span></a> </li> {% endif %} {% for item in paginator.page_range %} {% if item == current_page_num %} <li class="active"><a href="?page={{ item }}">{{ item }}</a></li> {% else %} <li><a href="?page={{ item }}">{{ item }}</a></li> {% endif %} {% endfor %} {# 下一页#} {% if current_page.has_next %} <li> <a href="?page={{ current_page.next_page_number }}" aria-label="Next"><span aria-hidden="true">下一页</span></a> </li> {% else %} <li class="disabled"> <a href="" aria-label="Next"><span aria-hidden="true">下一页</span></a> </li> {% endif %} </ul> </nav> </body> </html>
5、每页只显示10个,左边5个,右边5个
views
html
bug:
头部:如果current_page_num = 1则显示前5个数据
尾部:如果currnet_page_num=100 则多余显示后5个数据
views代码
from django.shortcuts import render from app01.models import Book from django.core.paginator import Paginator, EmptyPage # 分页器 def index(request): # 添加100条书籍数据 # 方式1: # for i in range(100): # Book.objects.create(title='book_%s' % i, price=i*i) # 方式2:生成100个实例对象,创建效率高 # book_list = [] # for i in range(100): # book_obj = Book(title="book_%s" % i, price=i*i) # book_list.append(book_obj) # # Book.objects.bulk_create(book_list) # 批量导入 # book_list = Book.objects.all() # 分页器的使用 # 1.对谁做分页, 每页几条数据 paginator = Paginator(book_list, 12) # 对book_list数据分页,每页10条数据 print('count:', paginator.count) # 数据总个数 100 print('num_page:', paginator.num_pages) # 总页数 9 print('per_page', paginator.per_page) # 每页显示条目数量 12 print('page_range', paginator.page_range) # 页码的列表 range(1, 10) print('page', paginator.page) # page对象 <django.core.paginator.Paginator object at 0x0412EAF0> # 2.显示某一页的具体数据的两种方法 # 方式1:固定页码num page1 = paginator.page(1) # 获取第1页的page对象 print("object_list", page1.object_list) # page的object_list属性 for item in page1: # for打印每条数据对象 print(item) # 方式2:动态获取当前页码num # print(request.GET) # http://127.0.0.1:8000/app01/index/?page=1 # current_page_num = int(request.GET.get("page", '1')) # 1 # <QueryDict: {'page': ['2']}> # current_page = paginator.page(current_page_num) # 3.抛出Empty异常 try: print(request.GET) # http://127.0.0.1:8000/app01/index/?page=1 current_page_num = int(request.GET.get("page", '1')) # 1 # <QueryDict: {'page': ['2']}> current_page = paginator.page(current_page_num) except EmptyPage as e: current_page = paginator.page(1) except ValueError as e: current_page = paginator.page(1) # 4.上一页,下一页 try: print(current_page.has_previous()) # 是否有上一页 print(current_page.previous_page_number()) # 上一页的页码 print(current_page.has_next()) # 是否有下一页 print(current_page.next_page_number()) # 下一页的页码 except EmptyPage as e: pass """ if 当前page对象有 上一页 <a href="?page={{ current_page.previous_page_number }}"> else: <a href=""> """ return render(request, 'index.html', locals()) def my_index(request): book_list = Book.objects.all() # 要分页的data paginator = Paginator(book_list, 3) # 怎么分页 current_page_num = int(request.GET.get('page', '1')) # 获取url中的?page=1 print(paginator.num_pages) # 总页数 100 print(paginator.page_range, type(paginator.page_range)) # 页码的列表 range(1, 101) <class 'range'> if paginator.num_pages > 11: if current_page_num < 5: # ?page=1,2,3,4,5 page_range = range(1, 12) elif current_page_num > paginator.num_pages-5: # ?page > 总num-5 page_range = range(paginator.num_pages-10, paginator.num_pages+1) else: # ?page=其他 page_range = range(current_page_num - 4, current_page_num + 6) else: page_range = paginator.page_range # 页码的总列表 range(1, 101) current_page = paginator.page(current_page_num) # 获取当前页的page对象 return render(request, 'my_index.html', locals())
模板层代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <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> {#book内容#} <ul> {% for book in current_page %} <li>{{ book.title }} : {{ book.price }}</li> {% endfor %} </ul> <nav aria-label="Page navigation"> <ul class="pagination"> {# 上一页#} {% if current_page.has_previous %} <li> <a href="?page={{ current_page.previous_page_number }}" aria-label="Previous"><span aria-hidden="true">上一页</span></a> </li> {% else %} <li class="disabled"> <a href="" aria-label="Previous"><span aria-hidden="true">上一页</span></a> </li> {% endif %} {#中间数字部分#} {# {% for item in paginator.page_range %} 所有的页码列表 #} {% for item in page_range %} {% if item == current_page_num %} <li class="active"><a href="?page={{ item }}">{{ item }}</a></li> {% else %} <li><a href="?page={{ item }}">{{ item }}</a></li> {% endif %} {% endfor %} {# 下一页#} {% if current_page.has_next %} <li> <a href="?page={{ current_page.next_page_number }}" aria-label="Next"><span aria-hidden="true">下一页</span></a> </li> {% else %} <li class="disabled"> <a href="" aria-label="Next"><span aria-hidden="true">下一页</span></a> </li> {% endif %} </ul> </nav> </body> </html>
4、解耦的分页器代码
1、总结,分页时需要做三件事:
- 创建处理分页数据的类
- 根据分页数据获取数据
- 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]
主url
from django.contrib import admin from django.urls import path, re_path, include urlpatterns = [ path('admin/', admin.site.urls), re_path(r'app01/', include(('app01.urls', 'app01'))) ]
分url
from django.urls import path, re_path, include from app01 import views urlpatterns = [ re_path(r'^blog/$', views.blog, name='blog') ]
2、views视图如何调用 页码函数
from django.shortcuts import render from app01.models import Book from app01.pagination import mypaginator # 导入分页py def blog(request): book_list = Book.objects.all() # 分页的对象 current_page_num = int(request.GET.get('page', '1')) # url中的?page=22 当前页码num show_data_num = 3 # 每页要显示几个obj对象 show_page_num = 11 # 页码list总共显示多少个 page_range, current_page = mypaginator(book_list, current_page_num, show_data_num, show_page_num) # 生成页码列表range return render(request, 'blog.html', locals())
3、重点:解耦后的页码函数
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger # 分页器 def mypaginator(book_list, current_page_num, show_data_num, show_page_num): paginator = Paginator(book_list, show_data_num) # 要分页的对象 all_page_num = paginator.num_pages # 总共的page数量 half_page = int(show_page_num / 2) try: current_page = paginator.page(current_page_num) # 当前页码总共要显示的obj对象 except EmptyPage: # http://127.0.0.1:8000/app01/blog/?page=-22 current_page = paginator.page(1) except PageNotAnInteger: # http://127.0.0.1:8000/app01/blog/?dafdsaf current_page = paginator.page(1) if all_page_num > show_page_num: if current_page_num < half_page + 1: page_range = range(1, show_page_num + 1) print('头部', page_range) elif current_page_num > all_page_num - half_page: page_range = range(all_page_num - show_page_num + 1, all_page_num + 1) print('尾部', page_range) else: page_range = range(current_page_num - half_page, current_page_num + half_page + 1) print('中间', page_range) else: page_range = range(1, all_page_num + 1) print('1', page_range) return page_range, current_page
4、武sir的page页码类
http://www.cnblogs.com/wupeiqi/articles/5246483.html
还 不明白
#!/usr/bin/env python # _*_coding:utf-8_*_ from django.utils.safestring import mark_safe class PageInfo(object): def __init__(self,current,totalItem,peritems=5): self.__current=current self.__peritems=peritems self.__totalItem=totalItem def From(self): return (self.__current-1)*self.__peritems def To(self): return self.__current*self.__peritems def TotalPage(self): #总页数 result=divmod(self.__totalItem,self.__peritems) if result[1]==0: return result[0] else: return result[0]+1 def Custompager(baseurl,currentPage,totalpage): #基础页,当前页,总页数 perPager=11 #总页数<11 #0 -- totalpage #总页数>11 #当前页大于5 currentPage-5 -- currentPage+5 #currentPage+5是否超过总页数,超过总页数,end就是总页数 #当前页小于5 0 -- 11 begin=0 end=0 if totalpage <= 11: begin=0 end=totalpage else: if currentPage>5: begin=currentPage-5 end=currentPage+5 if end > totalpage: end=totalpage else: begin=0 end=11 pager_list=[] if currentPage<=1: first="<a href=''>首页</a>" else: first="<a href='%s%d'>首页</a>" % (baseurl,1) pager_list.append(first) if currentPage<=1: prev="<a href=''>上一页</a>" else: prev="<a href='%s%d'>上一页</a>" % (baseurl,currentPage-1) pager_list.append(prev) for i in range(begin+1,end+1): if i == currentPage: temp="<a href='%s%d' class='selected'>%d</a>" % (baseurl,i,i) else: temp="<a href='%s%d'>%d</a>" % (baseurl,i,i) pager_list.append(temp) if currentPage>=totalpage: next="<a href='#'>下一页</a>" else: next="<a href='%s%d'>下一页</a>" % (baseurl,currentPage+1) pager_list.append(next) if currentPage>=totalpage: last="<a href=''>末页</a>" else: last="<a href='%s%d'>末页</a>" % (baseurl,totalpage) pager_list.append(last) result=''.join(pager_list) return mark_safe(result) #把字符串转成html语言 分页实例