Django 验证码组件
验证码
在WEB
开发中,验证码始终是一个绕不开的话题。
这里用Python
写一个非常简单的验证码,后期会将该功能封装成组件方便下载使用。
模块准备
需要用到以下模块。
from PIL import Image, ImageDraw, ImageFont
# 第三方模块
# Image : 生成图片
# ImageDraw : 图片上写子
# ImageFont : 控制字体样式
from io import BytesIO, StringIO
# 标准库
# 内存管理器模块
# BytesIO : 临时存储数据,返回二进制格式
# String : 临时存储数据,返回字符串格式
前置知识
页面上的<img>
标签里,src
可以是一个图片地址,也可以是二进制数据。
所以利用这一点,我们就可以让它生成出图片后返回二进制数据给src
。
代码书写
下面的代码是在Django
中书写的。
注释已经非常详细了。
def get_random():
return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
def get_code(request):
# 生成图片 颜色模式,尺寸,颜色(3原色,单词)
img_obj = Image.new("RGB", (430, 35), get_random())
# 产生画笔对象
img_draw = ImageDraw.Draw(img_obj)
# 字体样式(引入一下字体),字体大小
img_font = ImageFont.truetype("static/font/karen-2.otf", 30)
# 生成随机验证码
code = ""
for i in range(5):
random_upper = chr(random.randint(65, 90)) # 随机大写
random_lower = chr(random.randint(97, 122)) # 随机小写
random_int = str(random.randint(0, 9)) # 随机数字
temp = random.choice([random_lower, random_upper, random_int]) # 随机取出一个
# 写code到图片上,一个一个写,隔开距离
img_draw.text((i*60+80,0),temp,get_random(),img_font) # 写入位置(X,Y)、写入字符
# 拼接随机字符串
code += temp
request.session['code'] = code # 存入session中
io_obj = BytesIO() # 生成内存管理器对象,看成文件句柄即可
img_obj.save(io_obj, "png") # 图片写入内存
get_img = io_obj.getvalue() # 读取图片(二进制)
return HttpResponse(get_img)
代码封装
下面将上面的代码做成一个单独的模块。
这个模块只需要你输入宽高字体和验证码的字符数量就好了,其他都都做好了。
from PIL import Image, ImageDraw, ImageFont
from io import BytesIO, StringIO
import random
class ImageCode(object):
def __init__(self, width, height, font_body, font_num=4):
self.code = ""
self.img_obj = Image.new("RGB", (width, height), self.get_random())
self.img_draw = ImageDraw.Draw(self.img_obj)
self.img_font_x = (width / font_num)
self.img_font_y = height // 4
self.font_num = font_num
self.io_obj = None
font_size = int(height * 0.8)
self.img_font = ImageFont.truetype(font_body, font_size)
self.run()
def get_random(self):
return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)
def run(self):
for i in range(self.font_num):
random_upper = chr(random.randint(65, 90)) # 随机大写
random_lower = chr(random.randint(97, 122)) # 随机小写
random_int = str(random.randint(0, 9)) # 随机数字
temp = random.choice(
[random_lower, random_upper, random_int]) # 随机取出一个
# 写code到图片上,一个一个写,隔开距离
self.img_draw.text((i*self.img_font_x, self.img_font_y), temp, self.get_random(),
self.img_font) # 写入位置(X,Y)、写入字符
# 拼接随机字符串
self.code += temp
self.io_obj = BytesIO() # 生成内存管理器对象,看成文件句柄即可
self.img_obj.save(self.io_obj, "png") # 图片写入内存
def get_img(self):
return self.io_obj.getvalue() # 返回二进制的图片
def get_code(self):
return self.code # 返回图片上的验证码
页面刷新
页面刷新其实很好做。
我们只要拿到这个标签,对他的src
拼接一个?
即可。
<img id="code" src="/get_code/" width="430" height="35">
<script>
$("#code").on("click",function(){
let oldsrc = $(this).attr("src");
if (oldsrc.endsWith("?")){
$(this).attr("src",oldsrc.slice(0,oldsrc.length-1));
}else{
$(this).attr("src",oldsrc+"?");
}
})
</script>
效果展示
这是在本地测试时录得屏,四字符的。