分页是每个项目必不可少要写的一个功能,该篇文章就将记录一下使用ORM写分页的过程。

假设我们的数据库里面需要显示一些数据,而这个表中的数据大约有几千条数据,那么我们不可能将所有的数据都显示出来,那么就需要使用分页来显示一部分数据,使用页数来进行翻页。在下面这个过程,我以一个demo的形式进行叙述。

1.要想有许多数据,就要先创建一个存储数据的表,下面就使用模型类创建一个表。

class TeacherTest(models.Model):
id=models.AutoField(primary_key=True)
name=models.CharField(max_length=20)

可以看到,这个表创建成功后有两个字段,第一个字段是id,第二个字段是name。

2.分页可以说分为两大部分,第一部分就是考虑显示部分数据在界面上,第二部分就是考虑页码如何写。如果想象不出是什么样子,可以参考一下博客园的分页,如下图:

首先考虑第一部分:如何显示部分数据在前端上,而不是显示表中所有的数据。这种情况下,我们会考虑使用切片的知识,比如:字符串str1="abcdefg"想要获取到abc怎么办呢,就使用切片,str2=str1[0:3]这样,就可以获取到了abc这个字符串。同样我们可以查询出所有的数据,然后通过切片的方法只获取到第几条到第几条数据,这样的话就可以显示出部分的数据了。

我们定义一下,每页显示5条数据,那么使用orm显示第一页的数据就应该是:TeacherTest.objects.all()[0:5]。根据这个规律展开以下分析:

显示数据      页数  切片  切片分析

第1条-第5条数据       1     [0:5]          [(1-1)*5:1*5]

第6条-第10条数据     2          [5:10]        [(2-1)*5:2*5]

第11条-第15条数据   3          [10:15]      [(3-1)*5:3*5]

......

第m条-第n条数据         j          [m-1:n]    [(j-1)*5:j*5]

通过上面的分析,我们知道了页数与显示数据的切片的关系了,那么我们就可以解决了一个显示的问题。

orm显示数据的语句就是:TeacherTest.objects.all()[(页码-1)*5:页码*5]

点击页码按钮通过url传递参数,后端获取传递的页码数就可以显示对应的数据了。

3.通过上面分析已经解决了显示问题,那么接下来就要显示分页了。要想知道分页,首先要知道的就是有多少条数据,然后根据计算这些数据需要多少页来显示数据。

获取总数据量:TeacherTest.objects.count()

假设表中的数据量是26条数据,那么可以分6页,最后一页显示1条数据;数据量是27条,也是分6页,最后一页显示2条数据。所有我们可以先计算出每页显示5条数据的页数,然后再计算是否还有不足5条数据,如果还有不足5条数据需要显示,那么就再计算出每页显示5条数据的页数加上1页,就得出总页数了。

伪代码如下:

data_count=Teacher.objects.count()
# 满足每页5条数据的页数
page_five=data_count//5
# 计算是否有余数
page=data_count%5 if page==0:
# 总页数
page_num=page_five
else:
# 总页数
page_num=page_five+1

也可以使用divmod(a,b)函数来计算页数,如果不了解这个内置函数的话,可以通过网上查询来获悉这个函数的用法。

最后我们计算出了页码总数,就需要在前端显示分页的页码,通过我们点击给前端传递参数。如果将页数传递到前端的话,前端没有range可以让我们使用来遍历,显示每个页码,我们只能在后端做好后,将页码传递到前端。这里我使用的是html在后端拼接,然后传递到前端。下面可以参考具体的代码来学习:

后端代码:

def show_page(request):
if request.method=="GET":
current_page=request.GET.get("page") # 获取跳转的页数
current_page=int(current_page)
show_num=5 # 显示条数
"""
1-5条 [0:5] 1 [(1-1)*5:1*5]
6-10条 [5:10] 2 [(2-1)*5:2*5]
11-15条[10:15] 3 [(3-1)*5:3*5]
m-n条 [m-1:n] h [(m-1)*5:n*5]
"""
start_data=(current_page-1)*show_num # 从第几条数据显示
end_data=current_page*show_num # 显示到第几条技术 """
显示页数
"""
data_count=models.TeacherTest.objects.count() # 数据的总数量
m,n=divmod(data_count,show_num) page_list=[]
if n==0:
page_count=m
for p in range(1,page_count+1):
page='<li><a href="/app05/page/?page={0}">{0}</a></li>'.format(p)
page_list.append(page)
else:
page_count=m+1
for p in range(1,page_count+1):
page = '<li><a href="/app05/page/?page={0}">{0}</a></li>'.format(p)
page_list.append(page) show_data=models.TeacherTest.objects.all()[start_data:end_data]
return render(request,"page.html",{"allteacher":show_data,"pagecount":page_count,"page_list":page_list})

前端代码:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- Optional theme -->
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
</head>
<body>
<table class="table-bordered" border="1" width="300">
{% for teacher in allteacher %}
<tr>
<td>{{ teacher.id }}</td>
<td>{{ teacher.name }}</td>
</tr>
{% endfor %} </table>
<nav aria-label="Page navigation">
<ul class="pagination">
<li>
<a href="#" aria-label="Previous">
<span aria-hidden="true">&laquo;</span>
</a>
</li>
{% for page in page_list %}
{{ page|safe }}
{% endfor %}
<li>
<a href="#" aria-label="Next">
<span aria-hidden="true">&raquo;</span>
</a>
</li>
</ul>
</nav>
</body>
</html>

==============================================================================================================

此时分页就基本上写完了,但是我们在使用的时候会发现一个问题,就是如果有300条数据的时候,页数就会有60页,此时分页的页码就会全部显示到界面上,那样的话就显示不好看了。所以就要显示分页的长度了。

以下代码就是更新后的代码

def show_page(request):
if request.method=="GET":
current_page=request.GET.get("page") # 获取跳转的页数
current_page=int(current_page)
show_num=5 # 显示条数
"""
1-5条 [0:5] 1 [(1-1)*5:1*5]
6-10条 [5:10] 2 [(2-1)*5:2*5]
11-15条[10:15] 3 [(3-1)*5:3*5]
m-n条 [m-1:n] h [(m-1)*5:n*5]
"""
start_data=(current_page-1)*show_num # 从第几条数据显示
end_data=current_page*show_num # 显示到第几条技术 """
显示页数
"""
data_count=models.TeacherTest.objects.count() # 数据的总数量
page_count,n=divmod(data_count,show_num)
if n:
page_count+=1 # 总共展示11页
max_page=5
half_max_page=max_page//2
# 页面上展示的页码从哪开始
page_start=current_page-half_max_page
# 页面上展示的页码到哪结束
page_end=current_page+half_max_page
# 如果当前页加上一半比总页码数还大
if page_end>page_count:
page_end=page_count
page_start=page_count-max_page
# 如果当前页减去一半,比1还小
if page_start<=1:
page_start=1
page_end=max_page page_list=[]
for p in range(page_start,page_end+1):
page='<li><a href="/app05/page/?page={0}">{0}</a></li>'.format(p)
page_list.append(page) show_data=models.TeacherTest.objects.all()[start_data:end_data]
return render(request,"page.html",{"allteacher":show_data,"pagecount":page_count,"page_list":page_list})

Django框架之ORM的相关操作之分页(六)的更多相关文章

  1. Django框架之ORM的相关操作(一)

    一.一般操作 from django.db import models import datetime # Create your models here. class Author(models.M ...

  2. Django框架之ORM的相关操作之多对多三种方式(五)

    在之前的博客中已经讲述了使用ORM的多对多关系表,现在进行总结一下: 1.ORM自动帮助我们创建第三张表 2.手动创建第三张表,第三张表使用ForeignKey指向其他的两张表关联起来 3.手动创建第 ...

  3. Django框架之ORM的相关操作之一对一关系(四)

    ORM中一对一在当一张表的某一些字段查询的比较频繁,另外一些字段查询的不是特别频繁,那么就把不常用的字段单独拿出来做成一张表,然后通过一对一进行关联起来.举个例子:在我们登录某个账户的时候,一般会显示 ...

  4. Django框架之ORM的相关操作(二)

    模型类: class Commongity(models.Model): id=models.AutoField(primary_key=True) name=models.CharField(max ...

  5. Django框架06 /orm多表操作

    Django框架06 /orm多表操作 目录 Django框架06 /orm多表操作 1. admin相关操作 2. 创建模型 3. 增加 4. 删除 5. 修改 6. 基于对象的跨表查询 7. 基于 ...

  6. Django框架05 /orm单表操作

    Django框架05 /orm单表操作 目录 Django框架05 /orm单表操作 1. orm使用流程 2. orm字段 3. orm参数 4. orm单表简单增/删/改 5. orm单表查询 5 ...

  7. Django框架之ORM对表结构操作

    ORM的优点:(1)简单,不用自己写SQL语句 (2)开发效率高 ORM的缺点:对于不同的人写的代码,执行效率有差别 ORM的对应关系: 类  ---------->  数据表 对象------ ...

  8. django框架基础-ORM跨表操作-长期维护

    ###############    一对一跨表查询    ################ import os if __name__ == '__main__': os.environ.setde ...

  9. django框架基础-ORM单表操作-长期维护

    ###############    单表操作-添加数据    ################ import os if __name__ == '__main__': os.environ.set ...

随机推荐

  1. DES加密算法 转

    1.什么是对称密码算法 网络安全通信中要用到两类密码算法,一类是对称密码算法,另一类是非对称密码算法.对称密码算法有时又叫传统密码算法.秘密密钥算法或单密钥算法,非对称密码算法也叫公开密钥密码算法或双 ...

  2. sysbench下载与安装

    目标:下载.安装sysbench软件,做数据库压测 准备: 在sysbench启动的linux机器上,首先安装好mysql,查看mysql已经启动 例如,在机器上已经安装完mysql,其路径为 /us ...

  3. 赋值SQL语句

    UPDATE TAB_DEV_MS SET DT_DETECTION_STARTTIME = TO_DATE ( '2017-01-01 00:00:00', 'YYYY-MM-DD HH24:MI: ...

  4. GitBook相关使用以及配置笔记

    本地安装 GitBook的安装非常简单.您的系统只需满足这两个要求: NodeJS(推荐使用v4.0.0及以上版本) Windows,Linux,Unix或Mac OS X gitbook-cli 是 ...

  5. Jenkins - 基于 Docker 的 Jenkins 安装

    概述 安装 Jenkins 基于 Docker 这个有点 水一发 的性质... 场景 学习 Jenkins 第一步, 当然是安装 但是 安装的方法 很多 Jenkins 是基于 Java 的 所以是个 ...

  6. Go反射

    一.引入 不同语言的反射模型不尽相同,有些语言还不支持反射.<Go 语言圣经>中是这样定义反射的: Go 语言提供了一种机制在运行时更新变量和检查它们的值.调用它们的方法,但是在编译时并不 ...

  7. js的一些基础

    事件对象: 就是用来存储事件相关的信息 事件对象存储信息有: 事件的类别,如:click,keydown等等 点击事件的位置 点击的哪一个键 等等 用于阻止事件流,用于阻止浏览器默认动作(表单提交.a ...

  8. 【做题笔记】洛谷P1002过河卒

    虽说是 dp 入门题,但还是有很多细节需要注意 如果设 \(f_{x,y}\) 为目标地点为 \((x,y)\) 时走的种数,那么答案就是 \(f_{n,m}\) 在不考虑那只讨厌的马的情况下,对于任 ...

  9. hdu 6214 Smallest Minimum Cut(最小割的最少边数)

    题目大意是给一张网络,网络可能存在不同边集的最小割,求出拥有最少边集的最小割,最少的边是多少条? 思路:题目很好理解,就是找一个边集最少的最小割,一个方法是在建图的时候把边的容量处理成C *(E+1 ...

  10. no module named系列问题解决

    持续更新中~~~ 1.终端指令错误:no module named 'gdbm' 解决办法: sudo apt-get install python3.6-gdbm 2.终端无法定位软件包 解决办法: ...