Django之图形验证码

Django之图形验证码

目录

【1】静态图片

最基础的生成图片就是获取静态文件

html 复制代码
<div style="margin-left: 10px;">
    <img src="{% static 'img/img.png' %}" width="100%" height="37px">
</div>

【2】视图层绑定静态文件

python 复制代码
# urls.py
path('get_verify_img/', views.get_verify_img, name='get_verify_img'),
python 复制代码
# views.py
import os
from django.conf import settings

def get_verify_img(request):
    img_path = os.path.join(settings.BASE_DIR, 'Blog/static/img/img3.png')
    with open(img_path, 'rb') as f:
        data = f.read()
    return HttpResponse(data)
html 复制代码
<img src="{% url 'Blog:get_verify_img' %}" width="100%" height="37px">

【3】PIL生成图片(固定背景)

安装Pillow模块

shell 复制代码
pip install Pillow

导入

python 复制代码
from PIL import Image, ImageDraw, ImageFont

# Image:负责生成图片数据
# ImageDraw:在生成的图片上面添加相应数据
# ImageFont:添加相应数据时指定字体样式、大小、间距
python 复制代码
from PIL import Image, ImageDraw, ImageFont

def get_verify_img(request):
    # 图片名称
    img_name = 'verify.png'

    # 指定图像模式
    mode = 'RGB'
    # 指定图像尺寸
    size = (123, 37)
    # 指定图像颜色(颜色名或三原色盘)
    color = 'blue'
	
    # 创建图片对象
    img_obj = Image.new(mode=mode, size=size, color=color)

    # 设置图片保存路径
    img_path = os.path.join(settings.BASE_DIR, 'Blog/static/img', img_name)
    # 保存图片
    img_obj.save(img_path)
	
	# 读取图片
    with open(img_path, 'rb') as f:
        data = f.read()
    return HttpResponse(data)

【4】将图片存储在内存

要将数据临时存储在内存需要借助Python的IO模块

python 复制代码
from io import BytesIO, StringIO
# BytesIO:负责临时存储数据
# StringIO:负责取出数据

顺便把随机颜色做了

python 复制代码
def random_rgb():
    return random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)
python 复制代码
def get_verify_img(request):
    img_name = 'verify.png'

    # 指定图像模式
    mode = 'RGB'
    # 指定图像尺寸
    size = (123, 37)
    # 随机生成图像颜色
    color = random_rgb()

    img_obj = Image.new(mode=mode, size=size, color=color)

    # 创建存储内存空间
    io_obj = BytesIO()
    
    # 保存图片并指定后缀
    img_obj.save(io_obj, 'png')
    
    # 取出图片
    data = io_obj.getvalue()

    return HttpResponse(data)

【5】生成文本信息

先生成一个随机的五位数文本

python 复制代码
def random_word():
    # 0-9数字
    random_num = random.randint(0, 9)
    # a-z
    random_lower = chr(random.randint(97, 122))
    # A-Z
    random_upper = chr(random.randint(65, 90))
    word = random.choice([random_upper, random_lower, str(random_num)])
    return word
python 复制代码
def get_verify_img(request):
    img_name = 'verify.png'

    # 指定图像模式
    mode = 'RGB'
    # 指定图像尺寸
    size = (123, 50)
    # 随机生成图像颜色
    color = random_rgb()

    img_obj = Image.new(mode=mode, size=size, color=color)

    # 创建画笔对象
    img_draw = ImageDraw.Draw(img_obj)
    
    # 设置字体和大小
    img_font = ImageFont.truetype('Blog/static/font/TianShiBaoDiaoTiJian-1.ttf', 34)

    code = ''
    for i in range(0, 4):
        word = random_word()
        # text依次放入参数(坐标,文本内容,字体颜色,字体样式)
        img_draw.text((i * 15 + 20, 4), word, random_rgb(), img_font)
        code += word

        # 创建存储内存空间
        io_obj = BytesIO()
        
        # 保存图片并指定后缀
        img_obj.save(io_obj, 'png')
        
        # 取出图片
        data = io_obj.getvalue()
    return HttpResponse(data)

实例效果

【6】实现图片刷新

首先需要知道刷新图片的原理

当这种验证图片数据在开发者模式中将它的末尾添加?并加入任意数字后按下回车他就会自动变换

python 复制代码
http://127.0.0.1:8000/Blog/get_verify_img/
html 复制代码
<img src="{% url 'Blog:get_verify_img' %}" width="100%"
	height="37px" id="img_verify" alt="">

<script>
     const verify = document.getElementById('img_verify')
    verify.addEventListener('click', function () {
        // 获取原始的 src 属性值
        const verify_src = verify.src;
        // 检查原始 src 是否已经包含时间戳
        if (verify_src.includes('?')) {
            // 如果已经包含时间戳,只替换最后一个时间戳
            verify.src = verify_src.replace(/\?.*$/, '') + '?' + new Date().getTime();
        } else {
            // 如果原始 src 没有时间戳,直接添加时间戳
            verify.src = verify_src + '?' + new Date().getTime();
        }
    })
</script>

后端将生成图片验证码拆分到新的文件

python 复制代码
import random

from PIL import Image, ImageDraw, ImageFont
from io import BytesIO, StringIO


def random_rgb():
    return random.randint(0, 256), random.randint(0, 256), random.randint(0, 256)


def random_word():
    # 0-9数字
    random_num = random.randint(0, 9)
    # a-z
    random_lower = chr(random.randint(97, 122))
    # A-Z
    random_upper = chr(random.randint(65, 90))
    word = random.choice([random_upper, random_lower, str(random_num)])
    return word


def verify():
    img_name = 'verify.png'
    data = None
    # 指定图像模式
    mode = 'RGB'
    # 指定图像尺寸
    size = (100, 50)
    # 随机生成图像颜色
    color = random_rgb()

    img_obj = Image.new(mode=mode, size=size, color=color)

    img_draw = ImageDraw.Draw(img_obj)
    img_font = ImageFont.truetype('Blog/static/font/TianShiBaoDiaoTiJian-1.ttf', 35)

    code = ''
    words = ''
    for i in range(0, 4):
        word = random_word()
        # text依次放入参数(坐标,文本内容,字体颜色,字体样式)
        img_draw.text((i * 15 + 20, 4), word, random_rgb(), img_font)
        code += word

        # 创建存储内存空间
        io_obj = BytesIO()

        # 保存图片并指定后缀
        img_obj.save(io_obj, 'png')

        # 取出图片
        data = io_obj.getvalue()

        words += word
    print(words)
    # 返回图片数据,验证码文本
    return data,words

视图层代码

python 复制代码
# 文件路径自定义
from lib.verify_img.verify import verify

def get_verify_img(request):
    data, words = verify()
    print(words)
    return HttpResponse(data)
相关推荐
dfdfadffa4 小时前
如何用模块化方案组织一个可扩展的前端组件库项目
jvm·数据库·python
2301_812539674 小时前
SQL中如何高效实现分组数据的批量更新_利用窗口函数与JOIN
jvm·数据库·python
2501_901200534 小时前
如何实现SQL存储过程存储过程参数标准化_统一命名规范
jvm·数据库·python
运气好好的5 小时前
Golang怎么用embed嵌入SQL文件_Golang如何将SQL迁移文件嵌入Go程序统一管理【技巧】
jvm·数据库·python
念何架构之路5 小时前
MySql常见ORM
数据库·mysql
xcLeigh6 小时前
KES数据库安全、权限、审计实战
数据库·安全·备份·权限·审计·ssl加密·密码策略
zjy277776 小时前
c++如何实现日志文件的异步落盘功能_基于无锁队列方案【附代码】
jvm·数据库·python
河阿里6 小时前
SQL:深分页问题深度解析
数据库·sql
wang3zc6 小时前
JavaScript中函数声明位置对解析器预编译的影响
jvm·数据库·python
涤生大数据6 小时前
AI时代,SQL该何去何从?
数据库·人工智能·sql