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>

效果展示

   这是在本地测试时录得屏,四字符的。

   验证码

posted @ 2020-09-22 23:19  云崖先生  阅读(161)  评论(0编辑  收藏  举报