Django之验证码的实现,简单快捷的方法
实现验证码随网页变动即时刷新,实现有期限时间
请确保安装好pillow
直接show code:
0、路由urs.py
from django.urls import path, re_path
from . import views
urlpatterns = [
re_path(r'^test/$', views.testpage, name='test'),
re_path(r'^captcha/$', views.captcha, name='captcha'),
]
1、定义生成验证码views.py
import os, random, time, string, io
from django.shortcuts import render
from django.http import HttpResponse
from PIL import Image, ImageDraw, ImageFont
# 生成验证码,# 可以直接可以在html中的img引用
def captcha(request):
# 定义背景颜色、宽、高
bgcolor = (random.randrange(20, 100), random.randrange(20, 100), random.randrange(20, 100))
width = 100
height = 50
# 创建画面对象
img = Image.new('RGB', (width, height), bgcolor)
# 创建画笔对象
draw = ImageDraw.Draw(img)
# 调用画笔的point()函数绘制验证码的干扰点
for i in range(0, 100):
xy = (random.randrange(0, width), random.randrange(0, height))
fill = (random.randrange(0, 255), random.randrange(0, 255), 55)
draw.point(xy, fill=fill)
# 定义验证码的备选值
_str = string.digits + string.ascii_letters
# 随机取四个值作为验证码
rand_codes = ''.join(random.sample(_str, 4))
# 定义字体大小
size = int(min(width / len(rand_codes), height))
# 构造字体对象
font = ImageFont.truetype(r'C:\Windows\Fonts\Arial.ttf', size)
# 构造字体颜色,四个字颜色不同
for i in range(4):
fontcolor = (255, random.randrange(0, 255), random.randrange(0, 255))
draw.text((i * 25, 2), rand_codes[i], font=font, fill=fontcolor)
# 释放画笔
del draw
# # 将验证码缓存入session,后面做进一步验证,注意应该在这里存入的时候变为小写,
# 否则验证码过期就变成了空,再进行lower()操作会抛出异常
request.session['verify_code'] = rand_codes.lower()
# 验证码有效时间60秒
request.session.set_expiry(60)
print("生成的验证码是:", rand_codes)
print("它应该是与session存的验证码一样:", request.session['verify_code'])
buf = io.BytesIO()
img.save(buf, 'png')
# 将内存中的图片数据返回给客户端,MIME类型为png图片
return HttpResponse(buf.getvalue(), 'image/png')
# 这样也行
# return HttpResponse(buf.getvalue(), 'jpg')
关键点在于io.BytesIO()函数和它的getvalue()函数
BytesIO()使用的是Binary I/O(也叫buffered I/O)的方法,它的处理对象必须是字节类对象(bytes-like object),生成的对象是字节(bytes),这个过程不执行解码、编码和换行转换。这种类型的数据流可以用于所有非文本类的的数据(也就是二进制文件或二进制读取的文本,如图片、gif,以二进制读取的.txt,.py,.html等文件)。
而getvalue()返回储存在缓存中对象整个内容的字节
总之只要理解为:BytesIO()直接以二进制方式读取jpg、png、gif等文件并将它存于缓存中,而getvalue()方法则是将它从缓存中取出来,还原成原来的样子显示给我们看。
2、路由导航函数views.py
# 测试页
def testpage(request):
verify_msg = ''
_captcha_submit = request.POST.get('verify_code').lower()
# 注意这里提交的code需要小写,而服务器的code已经小写,
# 这样分开做是为了避免当验证码过期了变为空值取不到session抛出异常
_captcha_server = request.session.get('verify_code')
if _captcha_server == _captcha_submit:
return render(request, 'axf/test.html', {"msg": "验证成功"})
else:
verify_msg = '验证失败'
return render(request, 'testapp/test.html', {"msg": verify_msg})
3、模板下的HTML页test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>测试页面</title>
</head>
<body>
<form action="/test/" method="post">
<img src="/captcha/" alt="验证码"/>
<div>
<label>
<input type="text" name="verify_code" placeholder="请输入图片中验证码">
</label>
<input type="submit" value="验证"/>
</div>
</form>
<a>验证结果:</a>
<p style="color: red">{{msg}}</p>
</body>
</html>
展示结果:
验证码设置了60秒过期,如果过了60秒再输入验证码是不会成功的