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)
相关推荐
m0_748248021 小时前
Redis 简介与安装指南
数据库·redis·缓存
Elastic 中国社区官方博客6 小时前
在 Elasticsearch 中使用 Mistral Chat completions 进行上下文工程
大数据·数据库·人工智能·elasticsearch·搜索引擎·ai·全文检索
编程爱好者熊浪8 小时前
两次连接池泄露的BUG
java·数据库
TDengine (老段)9 小时前
TDengine 字符串函数 CHAR 用户手册
java·大数据·数据库·物联网·时序数据库·tdengine·涛思数据
qq7422349849 小时前
Python操作数据库之pyodbc
开发语言·数据库·python
姚远Oracle ACE10 小时前
Oracle 如何计算 AWR 报告中的 Sessions 数量
数据库·oracle
Dxy123931021610 小时前
MySQL的SUBSTRING函数详解与应用
数据库·mysql
码力引擎10 小时前
【零基础学MySQL】第十二章:DCL详解
数据库·mysql·1024程序员节
杨云龙UP11 小时前
【MySQL迁移】MySQL数据库迁移实战(利用mysqldump从Windows 5.7迁至Linux 8.0)
linux·运维·数据库·mysql·mssql
l1t11 小时前
利用DeepSeek辅助修改luadbi-duckdb读取DuckDB decimal数据类型
c语言·数据库·单元测试·lua·duckdb