二.图形验证码

Posted dbslinux

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了二.图形验证码相关的知识,希望对你有一定的参考价值。

# 图形验证码:

- 作用:注册页面
- 实现思路:
  - 生成4位字符串--产生随机数
  - 绘制图片--python的PIL包,但这里我不用它,我用第三包captcha来绘制
  - 响应,--告诉浏览器--指定数据类型为image/png
- pip install Pillow
- 解压拷贝capcha到libs中
- 实现:
  - 配置路由规则
  - 定义视图,调用capcha的方法
- 视图的逻辑:
  - 调用captcha生成图片数据
  - 保存文本到redis中
  - 输出图片数据

1.创建验证应用:

归根结底本质上就是显示一张图片,html中加一个img标签并指定src就行,但是注意它不是一张固定图片,思路:直接去请求一个视图,视图中去画一张图片出来,并在图片中写文字,再把图片保存到response响应对象中就可返回给浏览器.但有个问题,浏览器怎么知道你返回的是一张图片?--mime type数据格式---我们告诉浏览器我给你的二进制是图片imgae/jpg

capcha包中的capcha.py文件解说:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# refer to `https://bitbucket.org/akorn/wheezy.captcha`

import random
import string
import os.path
from io import BytesIO

from PIL import Image  #image相当于一张纸
from PIL import ImageFilter
from PIL.ImageDraw import Draw  #draw相当于一根笔
from PIL.ImageFont import truetype  #truetype是字体


class Bezier:  #封装绘图功能
    def __init__(self):
        self.tsequence = tuple([t / 20.0 for t in range(21)])
        self.beziers = {}

    def pascal_row(self, n):
        """ Returns n-th row of Pascal‘s triangle
        """
        result = [1]
        x, numerator = 1, n
        for denominator in range(1, n // 2 + 1):
            x *= numerator
            x /= denominator
            result.append(x)
            numerator -= 1
        if n & 1 == 0:
            result.extend(reversed(result[:-1]))
        else:
            result.extend(reversed(result))
        return result

    def make_bezier(self, n):
        """ Bezier curves:
            http://en.wikipedia.org/wiki/B%C3%A9zier_curve#Generalization
        """
        try:
            return self.beziers[n]
        except KeyError:
            combinations = self.pascal_row(n - 1)
            result = []
            for t in self.tsequence:
                tpowers = (t ** i for i in range(n))
                upowers = ((1 - t) ** i for i in range(n - 1, -1, -1))
                coefs = [c * a * b for c, a, b in zip(combinations,
                                                      tpowers, upowers)]
                result.append(coefs)
            self.beziers[n] = result
            return result


class Captcha(object):
    def __init__(self):
        self._bezier = Bezier()
        self._dir = os.path.dirname(__file__)
        # self._captcha_path = os.path.join(self._dir, ‘..‘, ‘static‘, ‘captcha‘)

    @staticmethod
    def instance():
        if not hasattr(Captcha, "_instance"):
            Captcha._instance = Captcha()
        return Captcha._instance

    def initialize(self, width=200, height=75, color=None, text=None, fonts=None):
        # self.image = Image.new(‘RGB‘, (width, height), (255, 255, 255))
        self._text = text if text else random.sample(string.ascii_uppercase + string.ascii_uppercase + 3456789, 4)
        self.fonts = fonts if fonts else             [os.path.join(self._dir, fonts, font) for font in [Arial.ttf, Georgia.ttf, actionj.ttf]]
        self.width = width
        self.height = height
        self._color = color if color else self.random_color(0, 200, random.randint(220, 255))

    @staticmethod
    def random_color(start, end, opacity=None):
        red = random.randint(start, end)
        green = random.randint(start, end)
        blue = random.randint(start, end)
        if opacity is None:
            return red, green, blue
        return red, green, blue, opacity

    # draw image

    def background(self, image):
        Draw(image).rectangle([(0, 0), image.size], fill=self.random_color(238, 255))
        return image

    @staticmethod
    def smooth(image):
        return image.filter(ImageFilter.SMOOTH)

    def curve(self, image, width=4, number=6, color=None):
        dx, height = image.size
        dx /= number
        path = [(dx * i, random.randint(0, height))
                for i in range(1, number)]
        bcoefs = self._bezier.make_bezier(number - 1)
        points = []
        for coefs in bcoefs:
            points.append(tuple(sum([coef * p for coef, p in zip(coefs, ps)])
                                for ps in zip(*path)))
        Draw(image).line(points, fill=color if color else self._color, width=width)
        return image

    def noise(self, image, number=50, level=2, color=None):
        width, height = image.size
        dx = width / 10
        width -= dx
        dy = height / 10
        height -= dy
        draw = Draw(image)
        for i in range(number):
            x = int(random.uniform(dx, width))
            y = int(random.uniform(dy, height))
            draw.line(((x, y), (x + level, y)), fill=color if color else self._color, width=level)
        return image

    def text(self, image, fonts, font_sizes=None, drawings=None, squeeze_factor=0.75, color=None):
        color = color if color else self._color
        fonts = tuple([truetype(name, size)
                       for name in fonts
                       for size in font_sizes or (65, 70, 75)])
        draw = Draw(image)
        char_images = []
        for c in self._text:
            font = random.choice(fonts)
            c_width, c_height = draw.textsize(c, font=font)
            char_image = Image.new(RGB, (c_width, c_height), (0, 0, 0))
            char_draw = Draw(char_image)
            char_draw.text((0, 0), c, font=font, fill=color)
            char_image = char_image.crop(char_image.getbbox())
            for drawing in drawings:
                d = getattr(self, drawing)
                char_image = d(char_image)
            char_images.append(char_image)
        width, height = image.size
        offset = int((width - sum(int(i.size[0] * squeeze_factor)
                                  for i in char_images[:-1]) -
                      char_images[-1].size[0]) / 2)
        for char_image in char_images:
            c_width, c_height = char_image.size
            mask = char_image.convert(L).point(lambda i: i * 1.97)
            image.paste(char_image,
                        (offset, int((height - c_height) / 2)),
                        mask)
            offset += int(c_width * squeeze_factor)
        return image

    # draw text
    @staticmethod
    def warp(image, dx_factor=0.27, dy_factor=0.21):
        width, height = image.size
        dx = width * dx_factor
        dy = height * dy_factor
        x1 = int(random.uniform(-dx, dx))
        y1 = int(random.uniform(-dy, dy))
        x2 = int(random.uniform(-dx, dx))
        y2 = int(random.uniform(-dy, dy))
        image2 = Image.new(RGB,
                           (width + abs(x1) + abs(x2),
                            height + abs(y1) + abs(y2)))
        image2.paste(image, (abs(x1), abs(y1)))
        width2, height2 = image2.size
        return image2.transform(
            (width, height), Image.QUAD,
            (x1, y1,
             -x1, height2 - y2,
             width2 + x2, height2 + y2,
             width2 - x2, -y1))

    @staticmethod
    def offset(image, dx_factor=0.1, dy_factor=0.2):
        width, height = image.size
        dx = int(random.random() * width * dx_factor)
        dy = int(random.random() * height * dy_factor)
        image2 = Image.new(RGB, (width + dx, height + dy))
        image2.paste(image, (dx, dy))
        return image2

    @staticmethod
    def rotate(image, angle=25):
        return image.rotate(
            random.uniform(-angle, angle), Image.BILINEAR, expand=1)

    def captcha(self, path=None, fmt=JPEG):
        """Create a captcha.

        Args:
            path: save path, default None.
            fmt: image format, PNG / JPEG.
        Returns:
            A tuple, (name, text, StringIO.value).
            For example:
                (‘fXZJN4AFxHGoU5mIlcsdOypa‘, ‘JGW9‘, ‘x89PNG
x1a
x00x00x00
...‘)

        """
        image = Image.new(RGB, (self.width, self.height), (255, 255, 255))
        image = self.background(image)
        image = self.text(image, self.fonts, drawings=[warp, rotate, offset])
        image = self.curve(image)
        image = self.noise(image)
        image = self.smooth(image)
        name = "".join(random.sample(string.ascii_lowercase + string.ascii_uppercase + 3456789, 24))
        text = "".join(self._text)
        out = BytesIO()
        image.save(out, format=fmt)
        if path:
            image.save(os.path.join(path, name), fmt)
        return name, text, out.getvalue()

    def generate_captcha(self):
        self.initialize()
        return self.captcha("")

#那怎么用这个绘图功能呢?
captcha = Captcha.instance()   #实例化对象

if __name__ == __main__:
    print(captcha.generate_captcha())  #这样调用就能生成验证码数据


‘‘‘
怎么用呢?--它里边有这个__main__函数,所以直接单击这个文件右键---run就可输出如下了

(‘oNFHu6a9MyWvRtDQmTwhCXJY‘,
‘M5JK‘, ====>图片中的字符
图片的二进制数据==》b‘xffxd8xffxe0x00x10JFIFx00x01x01x00x00x01x00x01x00x00xffxdbx00Cx00x08x06x06x07x06x05x08x07x07x07		x08
x0cx14
x0cx0bx0bx0cx19x12x13x0fx14x1dx1ax1fx1ex1dx1ax1cx1c $.‘ ",#x1cx1c(7),01444x1f‘9=82<.342xffxdbx00Cx01			x0cx0bx0cx18

x182!x1c!22222222222222222222222222222222222222222222222222xffxc0x00x11x08x00Kx00xc8x03x01"x00x02x11x01x03x11x01xffxc4x00x1fx00x00x01x05x01x01x01x01x01x01x00x00x00x00x00x00x00x00x01x02x03x04x05x06x07x08	
x0bxffxc4x00xb5x10x00x02x01x03x03x02x04x03x05x05x04x04x00x00x01}x01x02x03x00x04x11x05x12!1Ax06x13Qax07"qx142x81x91xa1x08#Bxb1xc1x15Rxd1xf0$3brx82	
x16x17x18x19x1a%&‘()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzx83x84x85x86x87x88x89x8ax92x93x94x95x96x97x98x99x9axa2xa3xa4xa5xa6xa7xa8xa9xaaxb2xb3xb4xb5xb6xb7xb8xb9xbaxc2xc3xc4xc5xc6xc7xc8xc9xcaxd2xd3xd4xd5xd6xd7xd8xd9xdaxe1xe2xe3xe4xe5xe6xe7xe8xe9xeaxf1xf2xf3xf4xf5xf6xf7xf8xf9xfaxffxc4x00x1fx01x00x03x01x01x01x01x01x01x01x01x01x00x00x00x00x00x00x01x02x03x04x05x06x07x08	
x0bxffxc4x00xb5x11x00x02x01x02x04x04x03x04x07x05x04x04x00x01x02wx00x01x02x03x11x04x05!1x06x12AQx07aqx13"2x81x08x14Bx91xa1xb1xc1	#3Rxf0x15brxd1
x16$4xe1%xf1x17x18x19x1a&‘()*56789:CDEFGHIJSTUVWXYZcdefghijstuvwxyzx82x83x84x85x86x87x88x89x8ax92x93x94x95x96x97x98x99x9axa2xa3xa4xa5xa6xa7xa8xa9xaaxb2xb3xb4xb5xb6xb7xb8xb9xbaxc2xc3xc4xc5xc6xc7xc8xc9xcaxd2xd3xd4xd5xd6xd7xd8xd9xdaxe2xe3xe4xe5xe6xe7xe8xe9xeaxf2xf3xf4xf5xf6xf7xf8xf9xfaxffxdax00x0cx03x01x00x02x11x03x11x00?x00xf7xba(xa2xa8x02x8a(xa0x02x91Y[xeexb0?CU%x9exebxedxe9x02xdaxeexb6exf9xa6xddxf7Oxa6)xf6Vx16xfa|Mx1dxbax95Vmxc4x12O4x89xbdxdex85x9a(xaarxd9x06xbfx8exf1xaee@x83x1e^xec!xfax8ax06xd9rx8ax01x04dx1cx8a)x8c(xaa(xb3Gxa8I4x97xcamx88xc2xc3x81xf2x9fxd5xc0xeaxddx18x1fxa1xa4$xee:x8a23x8cxd1LaEWxbcxbaxfbx1dxabOxe5I.xdfxe0x8cdx9ax82xd2[xf9xaex8cxb2$ifxc8
)x1fxbcx07xdex95xc9rWxb1~x8a(xa6PQA x0cx93x8axc9xfexd2x96xf6xf0Exa6xc9x13,/xb6xe3x9x1fJMxd8NIx1axd4QE1x85x14Q@x05x14Q@x05x14Q@x05Pxd5gxb9xb7xb6x0fjxf0+x03x96xf3x8ex06*xfdpx972xcbsxe2x13-xebox82)xbcxaf(xf4Pzx1aLx89xbb+x1bvx9e/xd3.Fx1dxde‘x07x042xfexb4xe3xe2xcbx01|mUesxd02xaeAxad/xecxfbx15x8dxb1ox12xab.	xda:W+xa7hwz_x8ax17jx17xb3lx95nxa0fxa7TKsV:8xb5xdd:xe1x18}xa0Fxd8xe4?x04Qx06x95nxfasxdbxc9<xb70xcawnwxc9xfc
>xed4xc6YMxc0xb7xcax0fx9cxb0x1f.}k/xc3xf3xc9%xb5xe6x9cx93axe1?xbax93xaex14xf44xfdFxed{3xa1x86$x82x14x8a1x84Ax85x19xedYx1axfdxe3Dxf6x96ix9fxf4x99x02xb1x07x04x0exf5ax9bQxb1xb0x89U>xddqxbbx0exd9	xc7xadTt[xefx13xc7xb8x8cZGxb8xafxa3x1ax06xdex96Dx16zFx8dwspx88xd3Hxf16x1c30x00xd6xb0xd2xadx11@@xc9x81x81xb5x8dpx1axa6xadp<Mqx12xcb9x886x02Bpjkxabx88xe3xx8dxc5xdexa1n_xa6xe6xc8x15*Hxca5cxafx91xabx1cx8dcxe3Xxacxe1xb9x95xe3uxfdxe0vxcf5xd9Wx9ahxb7x96x16zxfcxd7xb7xd7x85xc2x8cFxe7x92xdfZxdex9bxc7x10xc8xc6=:xca{x993x81x81x80}xe8SKqBxb4bx9f3xeauxa7x80Mrqxf8xd1x7fxb6xfexc1-xafx967xecxdcZxb3xcfx89xbcOx93x8d+x8fxfaxe6kx9dxd7-xf55xb9MFxf2xd4[xb4xa7 xafxafxf4xa5*x9dx88xa9x89xd2xf0xbfxdczx9dxd7xdbx8cxd0}x93xc9xf2xb3xfbxddxfdqxedR^Oxf6{Ydx0cxa1x95Ix195xc4iPxebxfe!xb3x8eCxaax08xedxc1xc1xd9xc3x0cUxabx8fx04xdexafxefxf5x99dxdbxd3p4xf9x9bxd5#EVm^1ex8d:x19uxdd7xedx17x9ax94x89xe6x12x02Fxc1p3XxbaNxa64?x12xcbdnwYxe4xa9g==xf3Rxx7fxc2xd6xf7xf1xacxf7x17
xf0xcaSxe4l
xc7xd6xf4x03gxaexadx8dxaaxc9 p
x96xe4x9ax86xe5dxecc9TINxdfx89xd4xdfxxd1^xf5 xd2xcaxcbxce>`~sxe8+oLxd7xadxf5	x9axd8xabCtx9fz‘xebY6xb6Vxda$,.l"Hxa1Mxcbtxc4x12xcfxf4xacOx0bxdaxdfjxbaxecxbax98x9cxa2xa3xfcxccFwx0fJxbefx9exa6x8axa4xd4x92zxb6z=x14QZx1dAEx14Px01Ex14Px01wx8a!xfb>xa0x19cbxb7Qxecxf9Gxf1x8ex84xd7cYx9axedxb3Oxa73xc6xa0xcbx11x12‘x1ex94x9axba"jxe8xa6x936xadxe17;x88x9bxcb xedxeax18Ux7f	kxadxa8[xfdx92xe3xfd|#x00x9fxe2x14x~xe9Mxfcxf0x84x0bx15xc2xf9xca=xfax1axe5xf58o4xfdBxecxdbxcax91y2x99x17‘
xcfxa7xafxd2xa1xbbjg)8xdaFx82xdfxecxf1xbdxcdxadxd0x0fx05xc3x05daxc1xf4xadx8bxa4x1aGx89xedgE	mpxbeSx01xc0xcfjxf3xd8xefxae&xbe7Lxad5xcewx06xee1[:xcdxcexbfxaaxdbDnxa0)lx14H
x0e>xa4xd4)xe8sxc6xbaxb3i]xdfCxbcxbcxf1x0ex95dxa4xcbyx1eAxc1U99xae2xcbxc4xd3xa5xfdxfcxf6vr<xe7*Oxf0x81xd2xb6xf4xaf	ixc7Kx8ep<xcbx99cxdc$~@$zW<xfaUxd5x86xa5-x9bI3xb99Dx84mx0fx9fxe5Txf9x8d&xeb;7xa7xa0x96>x1bxd5xf5;xd6xbciRxddxddxb7x16xddxcf>x82xafj~x15]1#xbexb8x99xefx11[xf7xcaxd9xe7=xc5T[;xed&xf6xdeSx14xf6xe5xe4x01x07x99xbb>xc6xbax7fx16xeaxf1Yhx8dx16xe0exb8]xaa:xfdi(xc5+xb2cJx9ax8brxfcIxb4xefx0exe8f$xbax82xcdYdx8dxfcxf1xf8xd6xbdxbdx95xb5xaaxedx82x08xe3x19xcfxcaxb8xaax1ex1aYWxc3xf6x82Sx96xd9xc7xd3xb5/xf6xc3.xbfxfdx99-xb9Pxc9xba93x9dxdfxe1Z+$tGx92);Zxe6xadaxf8xb2xc7xedxdax0cxc0x0cxb4cxxfc+rx99,bXx9e6x19x0cx084xdaxbaxb1xa4x972ix9e}xe0-Ymxeedxd3xe58x12x1cxa7xd6xbdx10xf21^;ux14xbax17x88xceFxd3x14xbbx87xd35xebvwQxdexdaGqx13x06Gx82+:oK>x876x16Ox95xc1xeex8cOx0cxc7xe4xddxeaqx9cxe4NNx0fxa5nxb5xbc-:xccxd1xa9x91Fx03x11xc8x15xcdixbax83x1fx18xdexdbylx88xebx9fx98`x92;x8ax9bxc6wwVZTsxdaxc8xc8VAxb8xad]xd2W5SJ
xf6(xf8xf6x1bxa9xadxa0xf2xf3xf6pxdf9xcfx19xf7xadx1dx03Hx9axc2xdaxd4xc3x>xcfxb3/x18xef‘xbejMx1exfax1fx11h[nx02x96exdb"xe7xf5xac}x0fQ}7xc4x0fxa3x19|xdbbHx8cxf5+xedSxa5xefxdcx8bGx99Oxb9xdaxd1Ex15xa1xd0x14QEx00x14QEx00x14x8dxf7x0fx19xe3xa5-x14x01xe53xffx00kxdejx93Egx0cxb1xb4x0exccx15O+xcf<xd2xe8xfaMxcexa5xaf,Zxa4wx0cx0f.[<xe3xd4xd7xa4Eipx9ax94x97x06xe1Lx0c0xb1x04x03x07xd75%xe4x12xcdlxebm(x82cxd2Mxb9xc5execxfaxb3x93xeaxd7|xd2mx9cxf7x884xcbm7LKx8b+Ex06#x86x089+x8csY:x0fx89xed_Lm.xfcxecxdc
+x1ex98>xb5xd8xd8^Cvxb2[yxa6i`xf9e%qx93Xxbaxa7x81xec/x0bIlMxbcxa7x9e>xefxe5Mxa7xbcKx94exa4xa9xfdxc4Z[xfdxafxc3x92xabxdcxcbx18xb3sx86x89xb0Hx1dx07xd2xa2x8bQxd6xf5x1bx94x16xc2xd23xb7pxe7,x17xdex88|?wxa4xkPx85xa5Wgx1bx86xd3xd8Ukixb5x1bkdx9cxbdx8dxb0(x17xcex1cxb9x14j%}/xa1xad-xa4x16x08xf3xebwxc6xe5x9cmQx8cc=x80x15xccxddiw:xaexb3ogx0cmx1dxa2x8dxc8xa4xe7bxfbxfbxd4x96‘Rxd4xb5Yx80xcdxcbxe7jx95xf9x10zxe3xd6xbbx9d/M]:xdfc9x96Sxcbxc8zxb1xa2xca@xa2xaaxadxb4-[@xb6xd6xd1xc2x9fux14(xa96xa9mxdbF}qXxf7xbaxa5xf5xbdxe9xb6x8fOvWx18x8aaxcaxe7xfdxa1xd8Vx8dx9fxdaxbexcaxbflxf2xfcxffx00xe2xf2xfaUxa7xd0xddI7dOx90x0e	x14xb5xe5xfe*xbexd4xed5xe7
q"xa09x8fixc0xc5wx9a&xabx0exa1xa5xc3/x9cx86Mxa08xcfCRxa4x9bhx88VRx93x8fcx98xf8x85`6Azxabxcev1xa4xf0%xfdxe4xa0xd9xabxc5xf6xxceX7xdfxfc+Cxc6xf7xb6x8dxa2xb4x02hxda]xc3
x0eMsx9e
x91xed.nox042xcax88x98+x18xc995x0fJx874xedx1cBxb7]xcdxcdfxefxfbx17xc5x89x7f,,xf0xbc[rxa3xbdUxd7xb5xdfxedx9d*X#x89Sx07$3|xdfx95vf(5x1bXxda{pUx80mx92x0eGxd6xaaKxe1xfbx06xb7xxe1x88@xcfxffx00-#xe1x87xe3Vxd3:%	4xecxf4g%xa5hx1ax8cxfax0cRxd9Jxd6xd3x92Cx068xdcxb5xbfxa0xdixc5nnx98Ir:x11xd1kR{+x9fxb1Cx05xa5xd9x85xa3#22xee,=xeaxf2x82x14x02rqxd6x85x1bx0ex14xd2+Zxeax16xf7x93Mx14,Kxc2pxe0xa9x185jx90*xa9$(x04xf5xc0xa5xaa4Wxeax14QE1x85x14Q@x05x14Q@x05x14Q@x08x15Tx92x14x02zxe0Rxd1Ex006Hxd6Xx9a7x19Vx18"xb1xe2xf0xaex95x1bdxc0xe7#sx13x8axdaxa2x95x84xd2{x8cx8e(xe1@x91xa2xaax8ex00x03x15^;x1f/Qx92xefxedx12xb6xf1x8f(xb7xc8>x82xadxd1@4x98QEx14xc6`xxa7Axfexd9xb2x06%x1fix8fxeex13xdfxdaxbcxf1xb4Mjxd2Cx1axdbNx0fxfbx19xc1xafbxa2xa2Txd4x9dxcc*axe3Qxf3lxcf.xb0xf0Vxab|xeaxf7?xb9x8cxe0x92xe7$x8axf4-‘Ixb7xd2-x05xbdxb8xe3xa9cxd4x9axbfEx11x82x8exc3xa5Bx14xf6xdc(xa2x8axb3`xa2x8a(x00xa2x8a(x00xa2x8a(x03xffxd9‘)
‘‘‘

上述文件中,对象给我们创建好了,所以我们直接拿到这个对象调方法就好了,所以我接下来就写个视图,接收客户端的请求,来调类的方法,返回一个数据就完了。

技术图片

 

 

我单独创建一个应用--专负责验证的,因为我这个验证在注册模块用到,但别的模块也会用到.

技术图片

 

 verifycations/urls.py中:

这个url不是随便写的,这个js当中写好的,直接复制用就行

from django.conf.urls import url
from . import views
import uuid

urlpatterns = [
url(‘^image_codes/(?P<uuid>[w-]+)/$‘, views.ImageCodeView.as_view()),
]

根urls.py中包含:

from django.contrib import admin
from django.conf.urls import url,include

urlpatterns = [
    url(r^admin/, admin.site.urls),
    url(r^, include(users.urls)),
    url(^,include(verifycations.urls)),
]

views.py中:

from django.shortcuts import render
from django.views import View
from meiduo_mall.libs.captcha.captcha import captcha  #导入captcha对象
from django_redis import get_redis_connection  #连接redis
from . import constants
from django import http


class ImageCodeView(View):
    def get(self, request, uuid):
        # 接收
        # 验证
        # 处理:
        # 1.生成图片的文本、数据
        text, code, image = captcha.generate_captcha()

        # 2.保存图片文本,用于后续与用户输入值对比
        redis_cli = get_redis_connection(image_code) #连接缓存中配的image_code缓存
        redis_cli.setex(uuid, constants.IMAGE_CODE_EXPIRES, code)#往redis中写数据,键是uuid唯一标识,过期时间,值是code

        # 响应:输出图片数据
        return http.HttpResponse(image, content_type=image/png)#告诉浏览器这是图片类型

 

去注册:dev.py中追加:

INSTALLED_APPS = [
    .......verifycations.apps.VerifycationsConfig,
]

dev.py中增加图片验证的缓存项:

    "image_code": {  # 图形验证码
        "BACKEND": "django_redis.cache.RedisCache",
        "LOCATION": "redis://127.0.0.1:6379/2",
        "OPTIONS": {
            "CLIENT_CLASS": "django_redis.client.DefaultClient",
        }
    },

新建verifycations/constants.py过期时间文件:

#图片验证码在redis中的过期时间,单位是秒
IMAGE_CODE_EXPIRES = 60 * 5

以上是关于二.图形验证码的主要内容,如果未能解决你的问题,请参考以下文章

selenium基础-图形验证码

015 图像验证码

JSP 设计教师与学生不同登陆界面(带验证码)

原创干货 | Java代码审计之图形验证码模块

python web框架Flask——图形验证码及验证码的动态刷新

验证码识别——图形验证码