Django 学习组件分页器与自定制分页器
一.Django 分页器
1.django的分页器基础版
(1)首先是基础数据分别为
from django.db import models # Create your models here.
class Book(models.Model):
title = models.CharField(max_length=32)
price = models.DecimalField(max_digits=5, decimal_places=2)
models.py
from django.contrib import admin
from django.urls import path
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('book/', views.Book.as_view())
]
urls.py
(2)基础版的视图函数
from django.shortcuts import render, redirect
from django.views import View # 导入view
from app01 import models # 导入模型
from django.core.paginator import Paginator # 导入django分页器
import random # Create your views here.
class Book(View):
def get(self, request):
# 法二:批量增加测试数据 效率块
# book_list = []
# for i in range(1, 101):
# # models.Book.objects.create(title="book_%s" % i, price=random.randint(20, 300)) # 法一:执行效率低
# book_list.append(models.Book(title="book_%s" % i, price=random.randint(20, 300)))
# models.Book.objects.bulk_create(book_list) # 批量新增数据
# 分页器的基本语法
# book_list = models.Book.objects.all()
# print(book_list) # QuerySet book对象
# # 实例化分页对象
# paginator = Paginator(book_list, 10)
# print("count:", paginator.count) # 数据的总数
# print("num_pages:", paginator.num_pages) # 分页的总页数
# print("page_range:",paginator.page_range) # 页数的范围列表
#
# page1 = paginator.get_page(1) # 获取第一页的所有数据
# for i in page1: # 遍历第一页的所有数据对象
# print(i)
# print(page1.object_list) # 第一页的所用数据
# page2 = paginator.get_page(2) # 获取第二页的所有数据
# print(page2.has_next()) # 是否有下一页
# print(page2.next_page_number()) # 下一页的页码
# print(page2.has_previous()) # 是否有上一页
# print(page2.previous_page_number()) # 上一页的页码
# 当get不存在的页数或者填写其他类型的数据时会报错
# page=paginator.page(22) # error:EmptyPage
# page=paginator.page("z") # error:PageNotAnInteger # ############# django分页器的基本使用 ##################
book_list = models.Book.objects.all()
paginator = Paginator(book_list, 10) # 每页分的数量(数据量) current_page = int(
request.GET.get("page") if request.GET.get("page") and request.GET.get("page").isdigit() else 1) # 获取页码
page = paginator.get_page(current_page) # 获取当前页码的所有数据 return render(request, "book.html", {"paginator": paginator, "page": page, "current_page": current_page}) def post(self, request):
return redirect("/book/")
views.py
(3)最后是模板内容
<!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>
<h2>图书列表</h2>
<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">首页</a></li>
{% if page.has_previous %}
<li><a href="?page={{ page.previous_page_number }}">上一页</a></li>
{% else %}
<li class="disabled"><a href="javascript:void(0);">上一页</a></li>
{% endif %}
{% for num in paginator.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 %}
{% if page.has_next %}
<li><a href="?page={{ page.next_page_number }}">下一页</a></li>
{% else %}
<li class="disabled"><a href="javascript:void(0);">下一页</a></li>
{% endif %}
<li><a href="?page={{ paginator.num_pages }}">尾页</a></li>
</ul>
</nav> </body>
</html>
book.html
2.进阶版分页器
上面的示例,看似已经完成了分页的效果,但是,如果我们把每页显示的数量改小一点看一下效果。

显然这样不是我们想要的
(1)进阶版视图函数
from django.shortcuts import render, redirect
from django.views import View # 导入view
from app01 import models # 导入模型
from django.core.paginator import Paginator # 导入django分页器
import random # Create your views here.
class Book(View):
def get(self, request):
# ############# django分页器的基本使用进阶版 ##################
# 分页器的基本语法
book_list = models.Book.objects.all() # 示例分页器对象
paginator = Paginator(book_list, 2) # 每页显示数据的数量
current_page = int(
request.GET.get("page") if request.GET.get("page") and request.GET.get("page").isdigit() else 1)
# 获取页码
page = paginator.get_page(current_page) # 获取当前页码的所有数据
# 默认按照11个页码展示 if paginator.num_pages > 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 # 默认是10个页码
# if paginator.num_pages > 10:
# if current_page - 4 < 1:
# page_range = range(1, 11)
# elif current_page + 5 > paginator.num_pages:
# page_range = range(paginator.num_pages - 9, paginator.num_pages + 1)
# else:
# page_range = range(current_page - 5, current_page + 5)
#
# else:
# page_range = paginator.page_range
return render(request, "book.html", {
'paginator': paginator, "current_page": current_page, "page": page, "page_range": page_range
})
views.py
(2)模板内容
<!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>
<h2>图书列表</h2>
<ul> {# {% for book in page %}#}
{# <li>{{ book.title }} --- {{ book.price }}</li>#}
{# {% endfor %}#}
{% for p in page %}
<li>{{ p }}</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 href="javascript:void(0);" aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
{% endif %} {# 页码#}
{# {% for num in paginator.page_range %}#}
{% 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 %} {# 下一页#}
{% if page.has_next %}
<li>
<a href="?page={{ page.next_page_number }}" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
{% else %}
<li class="disabled">
<a href="javascript:void(0);" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
{% endif %} {# 尾页#}
<li>
<a href="?page={{ paginator.num_pages }}" aria-label="Next">
<span aria-hidden="true">尾页</span>
</a>
</li>
</ul>
</nav>
</body>
</html>
book.html
显示的效果为:

3.页码数设置奇数偶数优化版
(1)视图函数
from django.shortcuts import render
from django.views import View # 导入view
from app01 import models # 导入模型
from django.core.paginator import Paginator # 导入django分页器
import math
# Create your views here.
# 页码数设置奇数偶数优化版:只要设置page_num 页码即可,奇数偶数都兼容
class Book(View):
def get(self, request):
# ############# django分页器的基本使用进阶版 ##################
# 分页器的基本语法
book_list = models.Book.objects.all() # 示例分页器对象
paginator = Paginator(book_list, 2) # 每页显示数据的数量
current_page = int(
request.GET.get("page") if request.GET.get("page") and request.GET.get("page").isdigit() else 1)
# 获取页码
page = paginator.get_page(current_page) # 获取当前页码的所有数据
page_num = 11 # 设置页码个数,设置需要的个数可以为奇数,偶数
if paginator.num_pages > page_num: if current_page - math.floor(page_num/2) < 1:
page_range = range(1, page_num+1)
elif current_page + math.ceil((page_num-1)/2) > paginator.num_pages:
page_range = range(paginator.num_pages - (page_num-1), paginator.num_pages + 1)
else:
page_range = range(current_page - math.ceil((page_num-1)/2), current_page + math.floor((page_num+1)/2))
else:
page_range = paginator.page_range return render(request, "book.html", {
'paginator': paginator, "current_page": current_page, "page": page, "page_range": page_range
})
views.py
(2)模板内容
模板内容同上2的模板内容
效果图:奇数



效果图:偶数



二.自定制分页器
前提是已经在一上面的基础上,对视图和模板进行修改
1. 自定制分页器
(1)自定致分页器类
class Paginator:
def __init__(self, current_page, all_count, per_page=10, max_page_num=11):
"""
封装分页相关数据
:param current_page: 当前页码
:param all_count: 数据库中的数据总条数
:param per_page: 每个页面显示的数据条数
:param max_page_num: 最多显示的页码个数
:param num_pages: 通过总条数/每个页面显示的条数,求出总页数
"""
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_count = all_count
self.per_page = per_page # 计算总页数
num_pages, temp = divmod(all_count, per_page)
if temp:
num_pages += 1
self.num_pages = num_pages self.max_page_num = max_page_num #
self.page_count_half = int((self.max_page_num - 1) / 2) #
"""
self.num_pages=100
per_page=8 current_page =1 [0:8]
current_page =2 [8:16]
current_page =3 [16:24]
[(current_page-1)*per_page:current_page*per_page ] """ @property
def start(self):
return (self.current_page - 1) * self.per_page @property
def end(self):
return self.current_page * self.per_page def page_html(self):
# 如果总页数小于self.max_page_num(最多显示的页码个数)
if self.num_pages <= self.max_page_num:
page_start = 1
page_end = self.num_pages + 1
else:
# 如果当前页码<=页面上最多显示11/2个页码时
if self.current_page <= self.page_count_half:
page_start = 1
page_end = self.max_page_num + 1
# 如果当前页码+最多显示11/2 大于 总页数时
elif self.current_page + self.page_count_half > self.num_pages:
page_start = self.num_pages - self.max_page_num + 1
page_end = self.num_pages + 1
else:
page_start = self.current_page - self.page_count_half
page_end = self.current_page + self.page_count_half + 1 page_html_list = [] # 首页
first_page = '<nav aria-label="Page navigation"><ul class="pagination"><li><a href="?page=1">首页</a></li>'
page_html_list.append(first_page) # 上一页
if self.current_page <= 1:
prev_page = '<li class="disabled"><a href="javascript:void(0);">上一页</a></li>'
else:
prev_page = '<li><a href="?page=%s">上一页</a></li>' % (self.current_page - 1, )
page_html_list.append(prev_page) # 显示页码
for i in range(page_start, page_end):
if self.current_page == i:
temp = '<li class="active"><a href="?page=%s">%s</a></li>' % (i, i)
else:
temp = '<li><a href="?page=%s">%s</a></li>' % (i, i)
page_html_list.append(temp) # 下一页
if self.current_page >= self.num_pages:
next_page = '<li class="disabled"><a href="javascript:void(0);">下一页</a></li>'
else:
next_page = '<li><a href="?page=%s">下一页</a></li>' % (self.current_page + 1)
page_html_list.append(next_page) # 尾页
last_page = '<li><a href="?page=%s">尾页</a></li></ul></nav>' % self.num_pages
page_html_list.append(last_page) return "".join(page_html_list)
(2)视图函数
from django.shortcuts import render, redirect
from django.views import View # 导入view
from app01 import models # 导入模型
from app01.page import Paginator # 导入自定制的分页器 class Book(View):
def get(self, request):
book_list = models.Book.objects.all()
current_page = request.GET.get('page')
# 当前页数 数据总数 每页数据量 分页量
paginator = Paginator(current_page, book_list.count(), 6, 11)
book_list = book_list[paginator.start: paginator.end] return render(request, "book.html",
{"book_list": book_list, "paginator": paginator, "current_page": current_page})
views.py
(3)模板函数
<!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>
<h2>图书列表</h2>
<ul>
{% for book in book_list %}
<li>{{ book.title }} --- {{ book.price }}</li>
{% endfor %}
</ul> {{ paginator.page_html|safe }} </body>
</html>
book.html
效果图:

2.终极版本分页器
为什么需要终极版本呢,因为上面都还有些缺陷,那就是如果请求头还有其他数据,换页后会消失。
(1)终极版自定义分页类
class Paginator:
def __init__(self, request, current_page, all_count, per_page=10, max_page_num=13):
"""
封装分页相关数据
:param current_page: 当前页码
:param all_count: 数据库中的数据总条数
:param per_page: 每个页面显示的数据条数
:param max_page_num: 最多显示的页码个数
:param num_pages: 通过总条数/每个页面显示的条数,求出总页数
"""
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_count = all_count
self.per_page = per_page # 计算总页数
num_pages, temp = divmod(all_count, per_page)
if temp:
num_pages += 1
self.num_pages = num_pages self.max_page_num = max_page_num #
self.page_count_half = int((self.max_page_num - 1) / 2) # import copy
self.url_args = copy.deepcopy(request.GET)
print(self.url_args.urlencode()) """
self.num_pages=100
per_page=8 current_page =1 [0:8]
current_page =2 [8:16]
current_page =3 [16:24]
[(current_page-1)*per_page:current_page*per_page ] """ @property
def start(self):
return (self.current_page - 1) * self.per_page @property
def end(self):
return self.current_page * self.per_page def page_html(self):
# 如果总页数小于self.max_page_num(最多显示的页码个数)
if self.num_pages <= self.max_page_num:
page_start = 1
page_end = self.num_pages + 1
else:
# 如果当前页码<=页面上最多显示11/2个页码时
if self.current_page <= self.page_count_half:
page_start = 1
page_end = self.max_page_num + 1
# 如果当前页码+最多显示11/2 大于 总页数时
elif self.current_page + self.page_count_half > self.num_pages:
page_start = self.num_pages - self.max_page_num + 1
page_end = self.num_pages + 1
else:
page_start = self.current_page - self.page_count_half
page_end = self.current_page + self.page_count_half + 1 page_html_list = [] # 首页
self.url_args['page'] = 1
first_page = '<nav aria-label="Page navigation"><ul class="pagination"><li><a href="?%s">首页</a></li>' % (self.url_args.urlencode())
page_html_list.append(first_page) # 上一页
if self.current_page <= 1:
prev_page = '<li class="disabled"><a href="javascript:void(0);">上一页</a></li>'
else:
self.url_args['page'] = self.current_page - 1
prev_page = '<li><a href="?%s">上一页</a></li>' % (self.url_args.urlencode(), )
page_html_list.append(prev_page) # 显示页码
for i in range(page_start, page_end):
self.url_args['page'] = i
if self.current_page == i:
temp = '<li class="active"><a href="?%s">%s</a></li>' % (self.url_args.urlencode(), i)
else:
temp = '<li><a href="?%s">%s</a></li>' % (self.url_args.urlencode(), i)
page_html_list.append(temp) # 下一页
if self.current_page >= self.num_pages:
next_page = '<li class="disabled"><a href="javascript:void(0);">下一页</a></li>'
else:
self.url_args['page'] = self.current_page + 1
next_page = '<li><a href="?%s">下一页</a></li>' % (self.url_args.urlencode(), )
page_html_list.append(next_page) # 尾页
self.url_args['page'] = self.num_pages
last_page = '<li><a href="?%s">尾页</a></li></ul></nav>' % self.url_args.urlencode()
page_html_list.append(last_page) return "".join(page_html_list)
page.py
(2)视图函数
from django.shortcuts import render, redirect
from django.views import View # 导入view
from app01 import models # 导入模型
from app01.page import Paginator # 导入自定制的分页器
class Book(View):
def get(self, request):
book_list = models.Book.objects.all()
current_page = request.GET.get('page')
paginator = Paginator(request, current_page, book_list.count(), 6, 11)
book_list = book_list[paginator.start: paginator.end] return render(request, "book.html", {"book_list": book_list, "paginator": paginator, "current_page": current_page})
views.py
(3)模板函数
模板函数同上即可
Django 学习组件分页器与自定制分页器的更多相关文章
- Django学习(3)模板定制
在Django学习(一)一首情诗中,views.py中HTML被直接硬编码在代码之中,虽然这样便于解释视图是如何工作的,但直接将HTML硬编码到视图却不算一个好主意.因为: 对页面设计进行的任何改变都 ...
- Django学习——分页器基本使用、分页器终极用法、forms组件之校验字段、forms组件之渲染标签、forms组件全局钩子,局部钩子
内容 1 分页器基本使用 2 分页器终极用法 3 forms组件之校验字段 1 前端 <!DOCTYPE html> <html lang="en"> &l ...
- [Django高级之批量插入数据、分页器组件]
[Django高级之批量插入数据.分页器组件] 批量插入数据 模板层models.py from django.db import models class Books(models.Model): ...
- django之ajax结合sweetalert使用,分页器和bulk_create批量插入 07
目录 sweetalert插件 bulk_create 批量插入数据 分页器 简易版本的分页器的推导 自定义分页器的使用(组件) sweetalert插件 有这么一个需求: 当用户进行一个删除数据 ...
- Django学习笔记(13)——Django的用户认证(Auth)组件,视图层和QuerySet API
用户认证组件的学习 用户认证是通过取表单数据根数据库对应表存储的值做比对,比对成功就返回一个页面,不成功就重定向到登录页面.我们自己写的话当然也是可以的,只不过多写了几个视图,冗余代码多,当然我们也可 ...
- Django学习笔记(14)——AJAX与Form组件知识补充(局部钩子和全局钩子详解)
我在之前做了一个关于AJAX和form组件的笔记,可以参考:Django学习笔记(8)——前后台数据交互实战(AJAX):Django学习笔记(6)——Form表单 我觉得自己在写Django笔记(8 ...
- Django学习之十二:Cache 缓存组件
目录 Django Cache 缓存组件 缓存逻辑伪代码 配置缓存源 可配置参数说明 01. Django的默认缓存 02. 基于Redis的django-redis 03. 自定义cache 04. ...
- Django学习之八:forms组件【对form舒心了】
目录 Django forms组件 bound and unbound form instance forms渲染有关 隐藏一个字段,不渲染它 form 校验 form类 ModelForm 利用Mo ...
- Django学习笔记(12)——分页功能
这一篇博客记录一下自己学习Django中分页功能的笔记.分页功能在每个网站都是必要的,当页面因需要展示的数据条目过多,导致无法全部显示,这时候就需要采用分页的形式进行展示. 分页在网站随处可见,下面展 ...
随机推荐
- jvm01
hotspot:是jvm的核心组件(或者名称),jvm 需要对class文件进行编译成cpu能直接运行的代码.hotspot会对频繁使用的class代码进行缓存,不会再次编译,类似于缓存 client ...
- NTP服务安装及时间同步
1.安装ntp服务命令 yum install -y ntp 2.常用NTP服务器地址: ntp1.aliyun.com ntp2.aliyun.com ntp3.aliyun.com ntp4.al ...
- 【C语言】将输入的10个数排序
代码: #include <stdio.h> int main() { ], t; int i, j, max; printf("请输入10个数:\n"); ; i & ...
- HDFS的常用命令
一.常用命令 二.其他命令
- SpringCloud全家桶学习之服务注册与发现及Eureka高可用集群搭建(二)
一.Eureka服务注册与发现 (1)Eureka是什么? Eureka是NetFlix的一个子模块,也是核心模块之一.Eureka是一个基于REST的服务,用于定位服务,以实现云端中间层服务发现和故 ...
- placeholder样式
.mdwh_txtmod_tp_inpshad input::-webkit-input-placeholder { /* WebKit browsers */ color: #cccccc; } . ...
- 获取 input type=file 上次文件的路径
可以通过 $('这个元素').val();得到全路径:
- React项目中遇到的那些坑
1.react中路由跳转后页面不置顶问题 问题: 从页面A跳转到页面B,页面A滚动到中间位置,跳转后页面B也会在中间位置 解决方法:在顶部组件的生命周期中进行判断,例如 componentWillRe ...
- PLSQL用户登录时报错: no listener
报错原因是因为服务没有开启,找到oracle的相应服务开启即可.
- MyBatis-Plus学习笔记(3):分页查询
依赖配置可参考:MyBatis-Plus学习笔记(1):环境搭建以及基本的CRUD操作 分页配置 @Configuration public class PlusConfig { @Bean publ ...