• 02: 自定义图片验证码插件


    1.1 自定义图片验证码插件

      1、使用插件注意事项

          1、 插件代码中指定了验证码图片的字体,这里需要下载对应字体放到project中,如:project/Monaco.ttf

          2、 在使用时需要使用session功能,所以需要执行:
              python manage.py makemigrations
              python manage.py migrate

          3、 安装Pillow模块,heck_code.py(依赖:Pillow,字体文件)

          4、 src属性后面加?,实现点击验证码图片自动更新(加?号因为如果url不变浏览器不会再次发送请求)

          5、我们定义的插件可以在project下新建utils目录,将定义的插件都放到这个目录中

          6、 Monaco.ttf字体下载:https://files.cnblogs.com/files/xiaonq/Monaco.zip

      2、实现图片验证码测试文件

    from app01 import views
    
    urlpatterns = [
        url(r'^login.html$', views.login),
        url(r'^check_code.html$', views.check_code),
    ]
    urls.py
    from io import BytesIO
    from django.shortcuts import HttpResponse,render
    from utils.check_code import create_validate_code
    
    def check_code(request):
        # data = open('static/imgs/avatar/20130809170025.png','rb').read()
        # return HttpResponse(data)
    
        # 1. 创建一张图片 pip3 install Pillow
        # 2. 在图片中写入随机字符串
        # obj = object()
        # 3. 将图片写入到指定文件
        # 4. 打开指定目录文件,读取内容
        # 5. HttpResponse(data)
        stream = BytesIO()                      #就相当于在内存中打开了一个文件
        img, code = create_validate_code()      #生成图片对象和验证码文字
        img.save(stream,'PNG')                  #生成一个图片到内存中
        request.session['CheckCode'] = code    #将生成图片放到对应用户的session中
        return HttpResponse(stream.getvalue())
        # stream.getvalue()读取出内存中生成的那张图片
    
    def login(request):
        if request.method == 'POST':
            code = request.POST.get('check_code')   #获取前端传来的验证码图片
            if code.upper() == request.session['CheckCode'].upper():
                print('验证码正确')
            else:
                print('验证码错误')
        return render(request, 'login.html')
    views.py
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <div class="login">
            <form role="form" action="/login.html" method="POST">
                <div>
                {% csrf_token %}
                    <label for="password">验证码</label>
    
                    <div>
                        <div style="float: left">
                            <input type="text" class="form-control" placeholder="请输入验证码" name="check_code">
                        </div>
                        <div style="float: left;">
                            <img src="/check_code.html" onclick="changeCheckCode(this);">
                            <!--<img src="/static/imgs/11111.jpg">-->
                        </div>
                    </div>
                </div>
                <button type="submit" class="btn btn-default">登 陆</button>
            </form>
        </div>
        <script>
            function changeCheckCode(ths){
                ths.src = ths.src +  '?';
                //url没变浏览器不然重新发验证码,这里加?号就改变url了
            }
        </script>
    </body>
    </html>
    login.html
    import random
    from PIL import Image, ImageDraw, ImageFont, ImageFilter
    
    _letter_cases = "abcdefghjkmnpqrstuvwxy"      # 小写字母,去除可能干扰的i,l,o,z
    _upper_cases = _letter_cases.upper()            # 大写字母
    _numbers = ''.join(map(str, range(3, 10)))      # 数字
    init_chars = ''.join((_letter_cases, _upper_cases, _numbers))
    
    def create_validate_code(size=(120, 30),
                             chars=init_chars,
                             img_type="GIF",
                             mode="RGB",
                             bg_color=(255, 255, 255),
                             fg_color=(0, 0, 255),
                             font_size=18,
                             font_type="Monaco.ttf",    #设置验证码字体
                             length=4,
                             draw_lines=True,
                             n_line=(1, 2),
                             draw_points=True,
                             point_chance=2):
        width, height = size                        # 宽高
        img = Image.new(mode, size, bg_color)       # 创建图形
        draw = ImageDraw.Draw(img)                  # 创建画笔
    
        def get_chars():
            """生成给定长度的字符串,返回列表格式"""
            return random.sample(chars, length)
    
        def create_lines():
            """绘制干扰线"""
            line_num = random.randint(*n_line)  # 干扰线条数
            for i in range(line_num):
                begin = (random.randint(0, size[0]), random.randint(0, size[1]))    # 起始点
                end = (random.randint(0, size[0]), random.randint(0, size[1]))      # 结束点
                draw.line([begin, end], fill=(0, 0, 0))
    
        def create_points():
            """绘制干扰点"""
            chance = min(100, max(0, int(point_chance)))            # 大小限制在[0, 100]
            for w in range(width):
                for h in range(height):
                    tmp = random.randint(0, 100)
                    if tmp > 100 - chance:
                        draw.point((w, h), fill=(0, 0, 0))
    
        def create_strs():
            """绘制验证码字符"""
            c_chars = get_chars()
            strs = ' %s ' % ' '.join(c_chars)                      # 每个字符前后以空格隔开
            font = ImageFont.truetype(font_type, font_size)
            font_width, font_height = font.getsize(strs)
            draw.text(((width - font_width) / 3, (height - font_height) / 3),strs, font=font, fill=fg_color)
            return ''.join(c_chars)
        if draw_lines:
            create_lines()
        if draw_points:
            create_points()
        strs = create_strs()
        # 图形扭曲参数
        params = [1 - float(random.randint(1, 2)) / 100,
                  0,
                  0,
                  0,
                  1 - float(random.randint(1, 10)) / 100,
                  float(random.randint(1, 2)) / 500,
                  0.001,
                  float(random.randint(1, 2)) / 500
                  ]
        img = img.transform(size, Image.PERSPECTIVE, params)    # 创建扭曲
        img = img.filter(ImageFilter.EDGE_ENHANCE_MORE)         # 滤镜,边界加强(阈值更大)
        return img, strs                                       # img就是生成的图片对象,strs是生成的文字信息
    project/utils/check_code.py

       3、效果图

                       

  • 相关阅读:
    【Linux学习三】Linux系统目录架构
    【Linux学习二】Linux文件系统
    【Python网络爬虫四】通过关键字爬取多张百度图片的图片
    【GitHub】命令行操作
    【Linux学习一】命令行CLI、BASH的基本操作
    从CK+库提取标记点信息
    【Python网络爬虫三】 爬取网页新闻
    Windows命令行下pip安装python whl包
    【GitHub Desktop】MacOS和Win下配置及简单的使用
    【Python文件处理】递归批处理文件夹子目录内所有txt数据
  • 原文地址:https://www.cnblogs.com/xiaonq/p/8016743.html
Copyright © 2020-2023  润新知