页器
分页加载实现
views.py:
def get_students(request):
students=Student.objects.all()
# 指定页数
page_num=int(request.GET.get("page", 1))
# 将学生进行分页
paginator=Paginator(students, 10)
# 获取指定页面的学生
page=paginator.page(page_num)
data={
"students": page.object_list,
"page_object": page,
"page_range": paginator.page_range,
}
return render(request, 'StudentList.html', context=data)
# 绘制验证码
def get_verify_code(request):
# 设置画布大小
image_size=(200, 100)
# 设置画布背景颜色
image_color=get_color()
# 生成画布
image=Image.new("RGB", image_size, image_color)
# 导入字体 设置字体大小
image_font=ImageFont.truetype('/home/intro/django/day07/DjangoAdvanced/static/fonts/ADOBEARABIC-BOLD.OTF',
size=60)
# 生成画笔
image_draw=ImageDraw.Draw(image, "RGB")
# 字符串库
source_str="1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
dest_str=""
# 取四次字符
for i in range(4):
r=random.randrange(len(source_str))
dest_str +=source_str[r]
# 将dest_str存到session中
request.session['verifycode']=dest_str
# 起点,需要画的内容,实例化字体
# image_draw.text((20, 30), "q", font=image_font)
# image_draw.text((65, 30), "W", font=image_font)
# image_draw.text((110, 30), "e", font=image_font)
# image_draw.text((155, 30), "R", font=image_font)
for i in range(4):
image_draw.text((20 + 45 * i, 20), dest_str[i], fill=get_color(), font=image_font)
# 干扰点
for i in range(1000):
image_draw.point((random.randrange(200), random.randrange(100)), fill=get_color())
# 实例化一个IO流
buffer=BytesIO()
# 将图片存储到流中 格式是png
image.save(buffer, "png")
return HttpResponse(buffer.getvalue(), content_type="image/png")
# 生成随机颜色
def get_color():
r=random.randrange(256)
g=random.randrange(256)
b=random.randrange(256)
return (r, g, b)
# 返回登录界面
def user_login(request):
return render(request, 'UserLogin.html')
# 执行登录
def do_user_login(request):
#获取用户输入的验证码
verify_code=request.POST.get("verifycode")
#系统生成的验证码
dest_code=request.session.get('verifycode')
#判断输入的验证码是否正确,并且忽略大小写
if verify_code.lower()==dest_code.lower():
return HttpResponse('验证成功')
return HttpResponse("验证失败")
创建本地缓存的表
python manage.py createcachetable cachetable
# 使用装饰器 缓存时间为20s
@cache_page(20)
def get_sleeping(request):
sleep(5)
print("学习,断片了")
return HttpResponse("我不是故意的")
# 不使用装饰器 自己写缓存
def get_last(request):
# 从缓存中获取缓存
result=cache.get("get_last")
# 如果存在直接返回
if result:
return HttpResponse(result)
# 睡6s
sleep(6)
print("你完了")
students=Student.objects.all()
data={
"students": students,
}
#渲染模板 返回数据
result=loader.get_template('StudentList.html').render(context=data)
#保存缓存 cache.set(缓存名, 缓存数据, 缓存时长)
cache.set(request.META.get("REMOTE_ADDR") + 'get_last', result, timeout=20)
return HttpResponse(result)
homework
过本案例的学习,对于入门级的读者来说是个不错的学习体验,对于有基础的读者可以开拓思路。案例效果如下:
案例制作的思路是先将主页面制作好,然后以另存为的方法制作其他3个分页。其中,通过对类(.white)的静态传递,实现导航超链接背景色的改变。
首页index.html的代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" type="text/css" href="css/b5.css"/>
</head>
<body>
<div class="nav">
<ul>
<li class="white"><a href="tab1.html">首页</a></li>
<li><a href="news.html">新闻</a></li>
<li><a href="sport.html">体育</a></li>
<li><a href="music.html">音乐</a></li>
</ul>
</div>
<div class="nav-cont">
<img src="images/pic1.jpg"/>
</div>
</body>
</html>
分页news.html的代码如下,其他分页类似。
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" type="text/css" href="css/b5.css"/>
</head>
<body>
<div class="nav">
<ul>
<li><a href="tab1.html">首页</a></li>
<li class="white"><a href="news.html">新闻</a></li>
<li><a href="sport.html">体育</a></li>
<li><a href="music.html">音乐</a></li>
</ul>
</div>
<div class="nav-cont">
<img src="images/pic2.jpg"/>
</div>
</body>
</html>
外部样式文件b5.css的代码如下:
@charset "utf-8";
*{
margin:0px;
padding:0px;
}
body{
font-size:14px;
}
ul{
list-style-type:none;
}
.nav{
width:800px;
height:30px;
margin: 30pxauto 0px auto;
border-bottom:solid 1px #09f;
}
.nav ul li{
float:left;
width:70px;
margin: 0px 5px 0px 0px;
}
.nav ul li a{
display: block;
height:30px;
color:#333;
text-decoration: none;
border-top:solid 1px #09f;
border-left:solid 1px #09f;
border-right:solid 1px #09f;
text-align: center;
line-height:30px;
background:#8cd4fd;
}
.nav .white a{
background:#fff;
}
.nav-cont{
width:768px;
height:200px;
margin: 0px auto;
border-bottom:solid 1px #09f;
border-left:solid 1px #09f;
border-right:solid 1px #09f;
padding:10px 15px;
}
至此,案例制作完成。
昨天介绍了Oracle分页实现方案,那么,mysql又是如何实现分页呢?
参考官网:https://dev.mysql.com/doc/refman/5.7/en/select.html
MySQL中实现分页查询:在数据量较小的情况下可使用limit查询来实现分页查询,在数据量大的情况下使用建立主键或唯一索引来实现,另外可通过order by对其排序。
The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants, with these exceptions:
先看一下limit语法
SELECT * FROM TABLE
[ORDER BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
LIMIT子句可以被用于强制 SELECT 语句返回指定的记录数。LIMIT接受一个或两个数字参数。参数必须是一个整数常量。
如果给定两个参数,第一个参数指定第一个返回记录行的偏移量,第二个参数指定返回记录行的最大数目。初始记录行的偏移量是 0(而不是 1)。
1.1、传统实现方式
一般情况下,客户端通过传递 pageNo(页码)、pageSize(每页条数)两个参数去分页查询数据库中的数据,在数据量较小(元组百/千级)时使用 MySQL自带的 limit 来解决这个问题
--pageNo:页码
--pagesize:每页显示的条数
select * from table limit (pageNo-1)*pageSize,pageSize;
1.2、建立主键或者唯一索引(高效)
在数据量较小的时候简单的使用 limit 进行数据分页在性能上面不会有明显的缓慢,但是数据量达到了 万级到百万级 sql语句的性能将会影响数据的返回。这时需要利用主键或者唯一索引进行数据分页;
--pageNo:页码
--pagesize:每页显示的条数
--假设主键或者唯一索引为 t_id
select * from table where t_id > (pageNo-1)*pageSize limit pageSize;
1.3、基于数据再排序
当需要返回的信息为顺序或者倒序时,对上面的语句基于数据再排序。order by ASC/DESC 顺序或倒序 默认为顺序
select * from table where t_id > (pageNo-1)*pageSize order by t_id limit pageSize;
Oracle中有专门的rownum()显示行号的函数,而MySQL没有专门的显示行号函数,但可以通过用@rownum自定义变量显示行号。
一般实现过程如下:
SELECT
(@rownum :=@rownum + 1) AS rownum,
t.*
FROM
table t,
(SELECT @rownum :=0) AS rn
3.1、环境准备
CREATE TABLE t (
EMPNO BIGINT ( 4 ) NOT NULL,
ENAME VARCHAR ( 10 ),
JOB VARCHAR ( 9 ),
MGR BIGINT ( 4 ),
HIREDATE date,
SAL BIGINT ( 10 ),
COMM BIGINT ( 10 ),
DEPTNO BIGINT ( 2 ),
PRIMARY KEY ( `EMPNO` )
) ENGINE=INNODB;
INSERT INTO t VALUES ('7369', 'SMITH', 'CLERK', '7902', '1980-12-17', '800', NULL, '20');
INSERT INTO t VALUES ('7499', 'ALLEN', 'SALESMAN', '7698', '1981-02-20', '1600', '300', '30');
INSERT INTO t VALUES ('7521', 'WARD', 'SALESMAN', '7698', '1981-02-22', '1250', '500', '30');
INSERT INTO t VALUES ('7566', 'JONES', 'MANAGER', '7839', '1981-04-02', '2975', NULL, '20');
INSERT INTO t VALUES ('7654', 'MARTIN', 'SALESMAN', '7698', '1981-09-28', '1250', '1400', '30');
INSERT INTO t VALUES ('7698', 'BLAKE', 'MANAGER', '7839', '1981-05-01', '2850', NULL, '30');
INSERT INTO t VALUES ('7782', 'CLARK', 'MANAGER', '7839', '1981-06-09', '2450', NULL, '10');
INSERT INTO t VALUES ('7788', 'SCOTT', 'ANALYST', '7566', '1987-04-19', '3000', NULL, '20');
INSERT INTO t VALUES ('7839', 'KING', 'PRESIDENT', NULL, '1981-11-17', '5000', NULL, '10');
INSERT INTO t VALUES ('7844', 'TURNER', 'SALESMAN', '7698', '1981-09-08', '1500', '0', '30');
INSERT INTO t VALUES ('7876', 'ADAMS', 'CLERK', '7788', '1987-05-23', '1100', NULL, '20');
INSERT INTO t VALUES ('7900', 'JAMES', 'CLERK', '7698', '1981-12-03', '950', NULL, '30');
INSERT INTO t VALUES ('7902', 'FORD', 'ANALYST', '7566', '1981-12-03', '3000', NULL, '20');
INSERT INTO t VALUES ('7934', 'MILLER', 'CLERK', '7782', '1982-01-23', '1300', NULL, '10');
commit;
3.2、limit分页
--查询第一页,每页显示5条数据
select * from t order by empno desc limit (1-1)*5,5;
--查询第二页,每页显示4条数据
select * from t order by empno desc limit (2-1)*4,4;
3.3、查询显示行号
--查询第二页,每页显示4条数据,并在第一列加上行号
select (@rownum :=@rownum + 1) AS rownum,t.* from t,
(SELECT @rownum :=0) AS rn
order by t.empno desc
limit 4,4;
觉得有用的朋友多帮忙转发哦!后面会分享更多devops和DBA方面的内容,感兴趣的朋友可以关注下~
*请认真填写需求信息,我们会在24小时内与您取得联系。