一.自定义分页器
import copy class Pagination(): def __init__(self,request,current_page,all_data_num,each_page_data_num=10,max_page_num=11): #封装页面相关数据 ''' current_page:当前页 data_num:数据总条数 each_page:每页数据条数 max_page_num:最大显示的页码数 page_num: 总页数 ''' self.url_data= copy.deepcopy(request.GET) # page =1&a=1&b=2 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_data_num = all_data_num #100 self.each_page_data_num =each_page_data_num # self.max_page_num = max_page_num #总大显示的页码数 # 计算总页数 total_page_num,tmp = divmod(self.all_data_num,self.each_page_data_num) if tmp: total_page_num +=1 self.total_page_num = total_page_num #总页数 self.page_count_half = int((self.max_page_num-1)/2) @property def start(self): return (self.current_page-1)*self.each_page_data_num @property def end(self): return self.current_page*self.each_page_data_num def page_html(self): #总页码 < 最大显示的页码数 if self.total_page_num <self.max_page_num: page_start = 1 page_end =self.total_page_num+1 #总页码 > 最大显示的页码数 else: if self.current_page <=self.page_count_half: page_start = 1 page_end =self.max_page_num+1 elif (self.current_page+self.page_count_half)>self.total_page_num: page_start=self.total_page_num-self.max_page_num+1 page_end =self.total_page_num+1 else: page_start =self.current_page-self.page_count_half page_end =self.current_page+self.page_count_half+1 page_html_lst=[] #首页,上一页标签 self.url_data["page"]=1 frist_page ='<nav aria-label="Page navigation"><ul class="pagination"><li><a href="?%s">首页</a></li>'%(self.url_data.urlencode(),) page_html_lst.append(frist_page) self.url_data["page"] = self.current_page-1 if self.current_page<=1: prev_page ='<li class="disabled"><a href="#">上一页</a></li>' else: prev_page = '<li><a href="?%s">上一页</a></li>'%(self.url_data.urlencode(),) page_html_lst.append(prev_page) #每页显示的页码 for i in range(page_start,page_end): self.url_data["page"] = i if i == self.current_page: tmp ='<li class="active"><a href="?%s">%s</a></li>' % (self.url_data.urlencode(), i,) else: tmp ='<li><a href="?%s">%s</a></li>' % (self.url_data.urlencode(), i,) page_html_lst.append(tmp) self.url_data["page"] = self.current_page + 1 if self.current_page >=self.total_page_num: next_page = '<li class="disabled"><a href="#">下一页</a></li>' else: next_page = '<li><a href="?%s">下一页</a></li>' % (self.url_data.urlencode(),) page_html_lst.append(next_page) self.url_data["page"] =self.total_page_num last_page = '<li><a href="?%s">尾页</a></li></ul></nav>' % (self.url_data.urlencode(),) page_html_lst.append(last_page) return "".join(page_html_lst)
自定义分页器的使用:
该分页器依赖:bootstrapt 的样式
pagination = Pagination(参数)
1. 最关键的两个参数:
1.当前页的页码 当前页码 reuqest.GET.get("page")
2.以及需要分页的数据条数
2. 该分页器 能做的:
1. 将数据分好页,且 通过该类的两个属性 ,可以得到当前页的数据范围 总数据进行切片 [pagination.start: pagination.end],得到当前页的数据,可以通过循环展示的页面。
2. pagination.page_html() 该方法,实现页码展示效果
保存搜索路径
1. 浏览器请求: http://127.0.0.1:8020/yema/?page=4&a=1&b=2&q=3
2.后端涉及到的知识点:
param = copy.deepcopy(request.GET) # 此字典可以变 ,通过 param["page"] = 值 改变 page 的页码
param.urlencode() # 把字典类型的数据转化成 此种格式的 数据 :page=4&a=1&b=2&q=3
后端实现逻辑:自定义分页器
from django.utils.safestring import mark_safe import copy class Pagination(object): def __init__(self,request,current_page,data_num,per_page_data_num,show_page_num): try: self.current_page = int(current_page) except Exception as e: #当前页码 self.current_page = 1 self.data_num = data_num # 数据总条数 self.per_page_data_num = per_page_data_num #没页显示的数据条数 self.show_page_num = show_page_num # 显示的页码条数 self.request = request #计算总页数 page_nums num,b = divmod(self.data_num,self.per_page_data_num) if b: self.page_nums = num+1 else: self.page_nums = num self.half_range = int((self.show_page_num-1)/2) @property def start(self): start = (self.current_page-1)*self.per_page_data_num return start @property def end(self): end = self.current_page*self.per_page_data_num return end @property def page_range(self): # 显示的页面数 show_page_num 11 #如果总页码数小于 show_page_num if self.page_nums<=self.show_page_num: page_range = range(1,self.page_nums+1) else: # 如果页面数大于show_page_num #如果当前页码数 +half 小于 show_page_num,就显示前show_page_num if (self.current_page+self.half_range)<= self.show_page_num: page_range = range(1,self.show_page_num+1) #如果当前页+half 大于 page_nums ,就显示最后show_page_num elif (self.current_page+self.half_range)>= self.page_nums: page_range = range(1,self.page_nums+1)[-self.show_page_num:] else: page_range = range(self.current_page-self.half_range,self.current_page+self.half_range) return page_range #页码的实现 def page_html(self): param = copy.deepcopy(self.request.GET) #首页 param["page"] = 1 first_page= '<nav aria-label="Page navigation"><ul class="pagination"><li>' '<a href="?%s"><span aria-hidden="true">首页</span> </a></li>'%param.urlencode() #上一页 param["page"] = self.current_page-1 if self.current_page-1>0: per_page = '<li><a href="?%s">' '<span aria-hidden="true">上一页</span> </a></li>'%(param.urlencode()) else: per_page = '<li><span aria-hidden="true" class="disabled">上一页</span></li>' page_body = '' #中间页 for num in self.page_range: param["page"] = num if self.current_page == num: page_h ='<li class ="active"><a href="?%s" >%s</a></li>'%(param.urlencode(),num) else: page_h = '<li> <a href="?%s">%s</a> </li>' % (param.urlencode(), num) page_body+= page_h #下一页 param["page"]=self.current_page+1 if self.current_page<self.page_nums: next_page = '<li><a href="?%s" aria-label="Next">' '<span aria-hidden="true">下一页</span></a></li>'%(param.urlencode()) else: next_page = '<li><span aria-hidden="true" class="disabled">下一页</span>' #尾页 param["page"] = self.page_nums last_page = '<li><a href="?%s"><span aria-hidden="true">尾页</span></a></li></ul></nav></li>'% param.urlencode() page_html = first_page+per_page + page_body + next_page+last_page return mark_safe(page_html)
二. Django 分页器的使用
1.批量创建数据
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
批量创建数据 book_list=[] for i in range(1,101): book=Book(name="book%s"%i,price=random.randint(100,900)) book_list.append(book) Book.objects.bulk_create(book_list)
2.django 分页器的用法
#django 分页器的使用 #总数据 book_lst=Book.objects.all()
#创建分页器对象 paginator = Paginator(book_lst,10) #参数 : 总数据,每页需要放的数据条数
print("总数据条数:",paginator.count) # 200 print("总共分了多少页:",paginator.num_pages) # 20 print("页码范围:",paginator.page_range) # range(1,21) page =paginator.get_page(3) #取第 3 页的数据 # paginator.get_page(n) 拿到第 n 页 的数据 # for book in page: # print(book) print("是否有下一页",page.has_next()) # 第3 页 有下一页 返回的是布尔值 :True print("是否有上一页",page.has_previous()) # 第 3 页有上一页 返回的是布尔值 :True print("下一页的数字:",page.next_page_number()) # 取到第3页的下一页数字4 print("上一页的数字:",page.previous_page_number()) #取第3页的上一页 数字 2
3. 实例
paginator =Paginator(data_list,10)
1.设计思路:
先从地址栏 发请求 的思路 开始考虑问题 http://127.0.0.1:8000/index/?page=3
地址栏 通过一个 page=1 的键值对 ,通过发get的请求给后端服务器, 后端通过 current_page= request.GET.get("page") 得到需要看的page数
通过 page_data = paginator .get_page(current_page) ,然后前端通过循环page_data 展示客户需要看的那一页数据
2. 设计 显示页码
后端逻辑:
book_list = Book.objects.all() paginator = Paginator(book_list,2) current_page=int(request.GET.get("page",1)) page = paginator.get_page(current_page) # 如果页数十分多时,换另外一种显示方式 , if paginator.num_pages>11: #页面最多显示的页码数 11表示:需要显示的页面码总数 ,以及上一页,下一页,首页 ,尾页 if current_page-5<1: page_range=range(1,12) elif current_page+5>paginator.num_pages: page_range=range(paginator.num_pages-10,paginator.num_pages+1) else: page_range=range(current_page-5,current_page+6) else: page_range=paginator.page_range return render(request,"index.html",{"page":page,"page_range":page_range,"current_page":current_page})
模板HTML
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css"
integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> <ul> {% for book in page %} <li>{{ book.title }}---{{ book.price }}</li> {% endfor %} </ul> <nav aria-label="Page navigation"> <ul class="pagination"> <li><a href="?page=1" aria-label="Previous"><span aria-hidden="true">首页</span></a></li> {% if page.has_previous %} <li><a href="?page={{ page.previous_page_number }}" aria-label="Previous"><span aria-hidden="true">上一页</span></a></li> {% else %} <li class="disabled"><a aria-label="Previous"><span aria-hidden="true">上一页</span></a></li> {% endif %} {% for num in page_range %} {% if num == current_page %} <li class="active"><a href="?page={{ num }}">{{ num }}</a></li> {% else %} <li><a href="?page={{ num }}">{{ num }}</a></li> {% endif %} {% endfor %} <li> <a href="#" > <span aria-hidden="true">下一页</span> </a> </li> <li> <a href="#" > <span aria-hidden="true">尾页</span> </a> </li> </ul> </nav> </body> </html>
2.django 分页器
from django.shortcuts import render from .models import Book from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger import random # Create your views here. def index(request): #批量创建数据 # book_list = [] # # for i in range(1,101): # book= Book(title="book_%s"%i,price=random.randint(100,600)) # # book_list.append(book) # # Book.objects.bulk_create(book_list) book_list = Book.objects.all() current_page = request.GET.get("page") #实例化分页器 paginator = Paginator(book_list,9) num_pages= paginator.num_pages #能分多少页 page_range = paginator.page_range # 页码范围 page = paginator.get_page(current_page) show_books = page.object_list print(page.has_previous()) #页码显示的个数 show_page_nums =11 show_page_nums = 11 if num_pages <show_page_nums: #num_pages<show_page_nums #展示所有的页码 page_range = page_range else: #正常当前页算出左右的页面数: half_num = int((show_page_nums-1)/2) #分页数大于11时: num_pages>show_page_nums #当前页或等于half_num就显示前面的11页 if int(current_page)<=half_num: #就显示 前 show_page_nums page_range = range(1,show_page_nums+1) elif (int(current_page)+half_num)>=num_pages: #就显示最后 show_page_nums 页 page_range = range(1,num_pages+1)[-show_page_nums:] else: page_range = range((int(current_page)-half_num),(int(current_page)+half_num)+1) return render(request,"index.html",{"book_list":show_books,"page_range":page_range,"current_page":int(current_page),"page":page,})
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 最新版本的 Bootstrap 核心 CSS 文件 --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@3.3.7/dist/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous"> </head> <body> {% for book in book_list %} <div>{{ book.title }}--------------{{ book.price }}</div> {% endfor %} <nav aria-label="Page navigation"> <ul class="pagination"> <li> {% if page.has_previous %} <a href="?page={{ page.previous_page_number }}" aria-label="Previous"> <span aria-hidden="true">上一页</span> </a> {% else %} <span aria-hidden="true" class="disabled"frd>上一页</span> {% endif %} </li> {% for num in page_range %} {% if current_page == num %} <li class="active"><a href="?page={{ num }}">{{ num }}</a></li> {% else %} <li><a href="?page={{ num }}">{{ num }}</a></li> {% endif %} {% endfor %} <li> {% if page.has_next %} <a href="?page={{ page.next_page_number }}" aria-label="Next"> <span aria-hidden="true">下一页</span> </a> {% else %} <span aria-hidden="true" class="disabled">下一页</span> </a> {% endif %} </li> </ul> </nav> </body> </html>