分页
-
一、分页基本原理:
from django.shortcuts import render # Create your views here. USER_LIST = [] for i in range(1, 666): dic = {'root':'root'+str(i), 'age':i} USER_LIST.append(dic) def index(request): # 获取当前页码 current_page = request.GET.get('p') current_page = int(current_page) # 设置上一页和下一页的页码 if current_page <= 1: prev_page = 1 else: prev_page = current_page - 1 next_page = current_page + 1 # 设置每页展示条目数 per_page_count = 10 # 计算展示数据的切片区间 start_item = (current_page - 1) * per_page_count end_item = current_page * per_page_count USER = USER_LIST[start_item: end_item] return render(request, 'index.html',{'USER': USER, 'prev_page': prev_page, 'next_page': next_page})
前端页面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% for item in USER %} <p>{{ item.root }}-{{ item.age }}</p> {% endfor %} <span><a href="?p={{ prev_page }}">上一页</a></span> <span><a href="?p={{ next_page }}">下一页</a></span> </body> </html>
展示样例:

-
二、Django 内置分页:
注意:
- 包括 Paginator、 Page 两个对象
- 页面调用的时候使用:include
from django.shortcuts import render from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger # 导入django分页模块 # Create your views here. # 模拟数据 USER_LIST = [] for i in range(1, 666): dic = {'root':'root'+str(i), 'age':i} USER_LIST.append(dic) def index1(request): # 获取当前页码 current_page = request.GET.get('p') # 创建 Paginator 对象,里面包括如下属性和对象: paginator = Paginator(USER_LIST, 10) # 需传入全部数据USER_LIST,如果是数据库数据则传入models.xx.objects.all()即可,后面的参数是每页展示条数 # 全部数据:USER_LIST,=》得出共有多少条数据 # per_page: 每页显示条目数量 # count: 数据总个数 # num_pages: 总页数,也可表示最后一页 # page_range: 总页数的索引范围,如: (1,10),(1,200) # page: page对象(封装着是否具有下一页;是否有上一页) try: # 创建 Page 对象,里面包括如下属性和对象: posts = paginator.page(current_page) # 需传入当前页current_page # has_next 是否有下一页 # next_page_number 下一页页码 # has_previous 是否有上一页 # previous_page_number 上一页页码 # object_list 分页之后的数据列表,已经切片好的数据 # number 当前页 # paginator paginator对象 except PageNotAnInteger: # 如果传入的页码不是整数,返回第一页 posts = paginator.page(1) except EmptyPage: # 如果传入的页码是空值,返回最后一页 posts = paginator.page(paginator.num_pages) return render(request, 'index1.html', {'posts': posts})
前端页面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for item in posts.object_list %} <p>{{ item.root }}-{{ item.age }}</p> {% endfor %} </ul> {% if posts.has_previous %} <a href="?p={{ posts.previous_page_number }}">上一页</a> {% else %} <a href="#">上一页</a> {% endif %} {% if posts.has_next %} <a href="?p={{ posts.next_page_number }}">下一页</a> {% endif %} <span> {{ posts.number }}/{{ posts.paginator.num_pages }} </span> </body> </html>
可以将 "翻页" 和 "页码展示" 的通用部分写入一个pager.html的文件中,所有页面直接使用 {% include %} 标签导入分页部分即可:
1、在templates文件夹下创建分页文件夹:例如下面的 include 文件夹
2、在 include 文件夹里创建分页部分的 html 文件:例如下面的 pager.html 文件

3、把分页和页码展示的通用部分放到 pager.html 文件中:pager.html 的内容如下
{% if posts.has_previous %} <a href="?p={{ posts.previous_page_number }}">上一页</a> {% else %} <a href="#">上一页</a> {% endif %} {% if posts.has_next %} <a href="?p={{ posts.next_page_number }}">下一页</a> {% endif %} <span> {{ posts.number }}/{{ posts.paginator.num_pages }} </span>
4、前端页面用 {% include %} 标签导入 pager.html 文件即可:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for item in posts.object_list %} <p>{{ item.root }}-{{ item.age }}</p> {% endfor %} </ul> {% include 'include/pager.html' %} </body> </html>
展示样例:

-
三、扩展Django内置分页—加入页码显示:
创建自定义的扩展分页类 CustomPaginator,继承 Paginator 类:
多传入两个自定义参数:
1、当前页码:current_page
2、显示的页码总数:per_pager_num,最好取奇数
一共需传入:
- 当前页
- 最多显示页码数:7
- 所有数据
- 每页显示条数:30
from django.shortcuts import render from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger # 导入django分页模块 # Create your views here. # 模拟数据 USER_LIST = [] for i in range(1, 666): dic = {'root': 'root' + str(i), 'age': i} USER_LIST.append(dic) # 扩展内置分页,创建自定义的扩展分页类 CustomPaginator,继承 Paginator 类 class CustomPaginator(Paginator): def __init__(self, current_page, per_pager_num, *args, **kwargs): # 当前页 self.current_page = int(current_page) # 页面下方最多显示的页码数量 11 self.per_pager_num = int(per_pager_num) super(CustomPaginator, self).__init__(*args, **kwargs) # 当前页 # self.current_page # 最多显示的页码数量 11 # self.per_pager_num # 总页数 # self.num_pages # 计算显示的页码数范围 def pager_num_range(self): # 总页数小于最多显示的页码数,range范围取1到总页数+1(开区间所以得+1) if self.num_pages < self.per_pager_num: # 总页数3页,显示的页码数11页 return range(1, self.num_pages+1) # 显示范围是 1-3页 # 总页数特别多 part = int(self.per_pager_num/2) # 算出最多显示页码数的一半,例如显示11页,此处就是5 # 处理选择页码数在1-5页的情况 if self.current_page <= part: # 当前页码数 <= 显示页数的一半 return range(1, self.per_pager_num+1) # 显示范围是 1-11页 # 处理选择页码数在最后5页的情况 if (self.current_page+part) > self.num_pages: # 当前页+显示页码数的一半 > 总页数 return range(self.num_pages-self.per_pager_num+1, self.num_pages+1) # 显示范围是 (总页数-显示页数+1) 到 最后一页 # 处理大多数中间页码的情况,例如当前页是第10页,显示范围是 5-15页 return range(self.current_page-part, self.current_page+part+1) # 显示范围是 当前页-显示页码数的一半 到 当前页+显示页码数的一半 def index2(request): # 获取当前页码 current_page = request.GET.get('p') # 创建 Paginator 对象,里面包括如下属性和对象: paginator = CustomPaginator(current_page, 11, USER_LIST, 10) # 需传入全部数据USER_LIST,如果是数据库数据则传入models.xx.all()即可,后面的参数是每页展示条数 # 全部数据:USER_LIST,=》得出共有多少条数据 # per_page: 每页显示条目数量 # count: 数据总个数 # num_pages: 总页数,也可表示最后一页 # page_range: 总页数的索引范围,如: (1,10),(1,200) # page: page对象(封装着是否具有下一页;是否有上一页) try: # 创建 Page 对象,里面包括如下属性和对象: posts = paginator.page(current_page) # 需传入当前页current_page # has_next 是否有下一页 # next_page_number 下一页页码 # has_previous 是否有上一页 # previous_page_number 上一页页码 # object_list 分页之后的数据列表,已经切片好的数据 # number 当前页 # paginator paginator对象 except PageNotAnInteger: # 如果传入的页码不是整数,返回第一页 posts = paginator.page(1) except EmptyPage: # 如果传入的页码是空值,返回最后一页 posts = paginator.page(paginator.num_pages) return render(request, 'index2.html', {'posts': posts})
前端页面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <ul> {% for item in posts.object_list %} <p>{{ item.root }}-{{ item.age }}</p> {% endfor %} </ul> {% if posts.has_previous %} <a href="?p={{ posts.previous_page_number }}">上一页</a> {% else %} <a href="#">上一页</a> {% endif %} <!--设置显示页码数--> {% for i in posts.paginator.pager_num_range %} {% if i == posts.number %} <a style='font-size: 30px' href="?p={{ i }}">{{ i }}</a> {% else %} <a href="?p={{ i }}">{{ i }}</a> {% endif %} {% endfor %} {% if posts.has_next %} <a href="?p={{ posts.next_page_number }}">下一页</a> {% endif %} <span> {{ posts.number }}/{{ posts.paginator.num_pages }} </span> </body> </html>
展示样例:

-
四、自定义分页:
- 自定义模块 pager.py 文件,创建自定义类 Pagination(object)
- 传入参数:
- 所有数据的总个数:models.xx.objects.all().count()
- 当前页码
- 每页显示条数:30
- 最多显示页码数:7
-
1、在所在应用文件夹里创建自定义模块 pager.py:

class Pagination(object): def __init__(self, totalCount, currentPage, perPageItemNum=10, maxPageNum=7): # 数据总个数 self.total_count = totalCount # 当前页码数 try: v = int(currentPage) if v <= 0: v = 1 self.current_page = v except Exception as e: self.current_page = 1 # 每页显示的条数 self.per_page_item_num = perPageItemNum # 最多显示页码数 self.max_page_num = maxPageNum # 计算展示数据切片开始值 def start(self): return (self.current_page - 1) * self.per_page_item_num # 计算展示数据切片结束值 def end(self): return self.current_page * self.per_page_item_num # 计算总页数 @property def num_pages(self): """ 总数据条数666,每页10条,需要判断666除以10的余数是否为0 如果余数为0,则总页数为商值 如果余数不为0,则总页数为商值+1 """ a, b = divmod(self.total_count, self.per_page_item_num) if b == 0: return a else: return a + 1 # 计算展示的页码范围 def pager_num_range(self): # 总页数小于最多显示的页数,range范围取1到总页数+1(开区间所以得+1) if self.num_pages < self.max_page_num: # 总页数3页,显示的页码数11页 return range(1, self.num_pages + 1) # 显示范围是 1-3页 # 总页数特别多 part = int(self.max_page_num / 2) # 算出最多显示页码的一半,例如显示11页,此处就是5 # 处理选择页码在1-5页的情况 if self.current_page <= part: # 当前页码 <= 显示页数的一半 return range(1, self.max_page_num + 1) # 显示范围是 1-11页 # 处理选择页码在最后5页的情况 if (self.current_page + part) > self.num_pages: # 当前页+显示页数的一半 > 总页数 return range(self.num_pages - self.max_page_num + 1, self.num_pages + 1) # 显示范围是 (总页数-显示页数+1) 到 最后一页 # 处理大多数中间页码的情况,例如当前页是第10页,显示范围是 5-15页 return range(self.current_page - part, self.current_page + part + 1) # 显示范围是 当前页-显示页码数的一半 到 当前页+显示页码数的一半 # 自定义前端分页页码样式 def page_str(self): # 创建一个空列表,用来保存各页码按钮样式的字符串 page_list = [] # 设置 "首页" 按钮 first = "<li><a href='?p=1'>首页</a></li>" page_list.append(first) # 设置 "上一页" 按钮:当前页-1 if self.current_page == 1: # 当前页是第一页 prev = "<li><a href='#'>上一页</a></li>" else: prev = "<li><a href='?p=%s'>上一页</a></li>" %(self.current_page-1) page_list.append(prev) # 设置中间页码按钮: for i in self.pager_num_range(): # 设置当前页按钮样式:class='active' if i == self.current_page: temp = "<li class='active'><a href='?p=%s'>%s</a></li>" %(i,i) # 其他页码按钮样式: else: temp = "<li><a href='?p=%s'>%s</a></li>" % (i, i) page_list.append(temp) # 设置 "下一页" 按钮:当前页+1 if self.current_page == self.num_pages: # 当前页是最后一页 nex = "<li><a href='#'>下一页</a></li>" else: nex = "<li><a href='?p=%s'>下一页</a></li>" % (self.current_page + 1) page_list.append(nex) # 设置 "尾页" 按钮 last = "<li><a href='?p=%s'>尾页</a></li>" %(self.num_pages) page_list.append(last) return ''.join(page_list)
-
2、配置静态css样式文件 bootstrap:

-
3、创建自定义分页 Pagination 对象,并传入参数:
from django.shortcuts import render from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger # 导入django分页模块 # Create your views here. # 模拟数据 USER_LIST = [] for i in range(1, 666): dic = {'root': 'root' + str(i), 'age': i} USER_LIST.append(dic) def index3(request): from app01.pager import Pagination # 导入自定义模块 pager.py 下的 Pagination 类 # 获取当前页码 current_page = request.GET.get('p') # 创建自定义分页类 Pagination 对象 page_obj = Pagination(666, current_page, perPageItemNum=10, maxPageNum=7) # 输出展示数据的切片区间 data_list = USER_LIST[page_obj.start(): page_obj.end()] return render(request, 'index3.html', {'data': data_list, 'page_obj': page_obj})
前端页面:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/bootstrap/css/bootstrap.css"> </head> <body> <ul> {% for item in data %} <p>{{ item.root }}-{{ item.age }}</p> {% endfor %} </ul> <!--引用自定义分页 Pagination 类中设置的页码样式--> <ul class="pagination pagination-sm"> {{ page_obj.page_str|safe }} </ul> </body> </html>
展示样例:
总结,分页时需要做三件事:
- 创建处理分页数据的类
- 根据分页参数获取数据
- 输出分页HTML,即:[上一页][1][2][3][4][5][下一页]

浙公网安备 33010602011771号