Django之图形验证码

【1】生成图片验证码

  • 依赖于pillow模块
  • pip install pillow
  • 使用pillow模块在导入时使用import PIL,而不是pillow

【1.1】Pillow图像生成模块

from PIL import Image, ImageDraw, ImageFont
# Image : 生成图片对象
# ImageDraw : 生成画笔对象
# ImageFont : 控制字体样式
# 图片对象
img_obj = Image.new(mode='',size=(width,height),color='颜色')
'''
mode: 图像模式,常见的包括 'L'(灰度图像)、'RGB'(真彩色图像)和 'RGBA'(带透明通道的图像)等。
size: 图像尺寸,以元组 (width, height) 的形式指定,表示图像的宽度和高度。
color: 图像的颜色,通常使用 RGB 或 RGBA 表示颜色,例如 (255, 0, 0) 表示红色,(0, 255, 0, 128) 表示半透明的绿色。
'''
# 常用方法
img_obj.open(filename, mode='r')  # 打开并加载图像文件。
img_obj.save(fp, format=None, **params)  # 保存图像到文件。
img_obj.resize(size, resample=3)  # 调整图像尺寸。
img_obj.rotate(angle, resample=0, expand=0, center=None, translate=None, fillcolor=None)  # 旋转图像。
img_obj.crop(box=None)  # 裁剪图像。
img_obj.filter(filter)  # 应用滤镜效果。
# 画笔对象
draw_obj = ImageDraw.Draw(im='')  # im: The image to draw in.
draw_obj = ImageDraw.Draw(im=img_obj)

# 常用方法
draw_obj.text(xy, text, fill=None, font=None, anchor=None, spacing=0, align="left")  # 在图像上绘制文本。
draw_obj.draw_obj.line(xy, fill=None, width=0, joint=None)  # 在图像上绘制直线。
draw_obj.pieslice(xy, start, end, fill=None, outline=None, width=0)  # 在图像上绘制扇形。
draw_obj.polygon(xy, fill=None, outline=None, width=0)  # 在图像上绘制多边形。
# 字体样式
font_obj = ImageFont.truetype(font, size, index=0, encoding='')  # 加载 TrueType 或 OpenType 字体文件。
font_obj = ImageFont.load_default()  # 加载默认字体。

# 常用方法
getsize(text): 返回给定文本的大小。
getmask(text, mode='', fill=0, direction=None, features=None): 返回给定文本的掩码。
getmetrics(): 返回字体的度量信息,如字符宽度、高度等。
getname(): 返回字体的名称。
get_variation_names(): 返回变体字体的名称。
get_variation_axes(): 返回变体字体的轴。

【1.2】io内存管理器模块

  • 使用io内存管理器创建数据流,生成速度快,且不会产生硬盘消耗
from io import BytesIO, StringIO
# BytesIO : 在内存中创建二进制数据流,可以像文件一样读取和写入字节数据。
# StringIO :在内存中创建字符串数据流,可以像文件一样读取和写入字符串数据。
# 生成对象
io_obj = BytesIO()  # 与文件句柄类似
# 常见方法
io_obj.read(size:int)  # 读取指定字节数的数据,如果未指定大小,则读取所有数据
io_obj.readline(size:int)  # 读取一行数据,如果未指定大小,则读取整行
io_obj.readlines(hint=-1)  # 读取所有行并返回列表,如果指定了 hint,则最多读取 hint 字节数据
io_obj.write(s)  # 向对象中写入数据。
io_obj.getvalue()  # 返回对象中的所有数据。
io_obj.seek(offset, whence=0)  # 移动文件指针到指定位置。
io_obj.tell()  # 返回当前文件指针的位置。
io_obj.truncate(size=None)  # 截断文件到指定大小,如果未指定大小,则截断到当前位置。
io_obj.flush()  # 将缓冲区的数据写入到流对象中。

【1.3】依赖Pillow模块和BytesIO对象实现生成图片验证码

from PIL import Image, ImageDraw, ImageFont, ImageFilter
import random
from io import BytesIO


def rgb_number():
    # 生成随机rgb色值的函数
    return random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)


# 创建图片验证码
def create_verify_code(img_type="RGB", img_size: tuple = (115, 34), img_rgb_number: tuple = None):
    if not img_rgb_number:
        # 如果没有指定,就生成一个随机的
        img_rgb_number = rgb_number()
    # 利用 Image 对象定义一个图片文件参数
    img_obj = Image.new(mode=img_type, size=img_size, color=img_rgb_number)
    # 图片的滤镜效果
    img_obj.filter(ImageFilter.UnsharpMask(radius=2, percent=150, threshold=3))
    # 利用 ImageDraw 对象产生一个画笔对象
    img_draw = ImageDraw.Draw(img_obj)
    # 利用 ImageFont 对象定义验证码字体参数(字体样式,字体大小)
    img_font = ImageFont.truetype('static/font/汉仪晴空体简.ttf', 30)

    # 创建随机验证码(数字 + 字母)
    code = ''

    for i in range(4):
        string_list = [
            str(random.randint(0, 9)),
            chr(random.randint(65, 90)),
            chr(random.randint(97, 122))
        ]
        temp = random.choice(string_list)

        # 借助画笔对象依次写入图片数据((x偏移值,y偏移值),写入内容,字体颜色,字体样式)
        img_draw.text((i * 25 + 10, 0), temp, fill=rgb_number(), font=img_font)
        # 拼接随机字符串
        code += temp

    # 随机验证码在登录的视图函数中需要比对,所以需要找地方存起来,便于其他函数调用

    # 生成 IO 对象 操作字节流数据
    io_obj = BytesIO()
    # 利用 Image 对象保存图片数据成指定格式
    img_obj.save(io_obj, "png")
    # 利用 IO 对象读取保存的图片字节数据
    img_data = io_obj.getvalue()

    # 返回生成的随机验证码和验证码的图片二进制数据
    return code, img_data
【1.3.1】使用方法
  • 将图片验证码渲染至img标签的src属性中
  • img标签的src属性,有三种方式可以渲染图片
    • 通过指定链接渲染图片http://
    • 通过本地路径渲染图片/static/
    • 通过二进制数据渲染图片
【1.3.1.1】后端
# 将上述代码封装至文件中
# views.py

from lib.GenerateVerifyCode import create_verify_code

def verify_code(request):
    captcha, img_data = create_verify_code()
    # 在做校验时需要使用,所以为其设置一个会话,指定会话的captcha属性
    request.session['captcha'] = captcha
    # 返回二进制图片数据
    return HttpResponse(img_data)

'''设置了session后,其他地方可以通过request.session.get('captcha')获取到验证码数据'''
【1.3.1.2】路由
  • 我们使用通过二进制数据渲染图片验证码
  • 可以通过反向解析执行视图函数
path('verify_code/', views.verify_code, name='verify_code')
【1.3.1.3】前端
  • 为图片验证码设置点击切换动作
<img src="{% url 'user:verify_code' %}"
 onclick="this.src='{% url 'verify_code' %}'+'?t='+ new Date().getTime();">
  • onclick:是为了在点击时切换图片,当每一次点击时,向后端发送一次请求
posted @ 2024-03-28 12:13  Lea4ning  阅读(82)  评论(0编辑  收藏  举报