首先安裝PIL包

 pip install pillow 

_

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

def get_chars_str():
    '''
    :return:驗證碼字符集合
    '''
    _letter_cases = "abcdefghjkmnpqrstuvwxy"  # 小寫字母,去除可能干擾的i,l,o,z
    _upper_cases = _letter_cases.upper()  # 大寫字母
    _numbers = ''.join(map(str, range(3, 10)))  # 數字
    init_chars = ''.join((_upper_cases, _numbers))
    return init_chars
def get_random_color():
    return (random.randint(1,255),random.randint(1,255),random.randint(1,255))
def create_validate_code(size=(200, 45),
                         chars=get_chars_str(),
                         img_type="gif",
                         mode="RGB",
                         bg_color=(get_random_color()),
                         fg_color=(0, 0, 255),
                         font_size=18,
                         font_type="utils/monaco.ttf",
                         length=5,
                         draw_lines=True,
                         n_line=(2, 4),
                         draw_points=True,
                         point_chance=2):
    """
    @todo: 生成驗證碼圖片
    @param size: 圖片的大小,格式(寬,高),預設為(120, 30)
    @param chars: 允許的字符集合,格式字符串
    @param img_type: 圖片保存的格式,預設為GIF,可选的为GIF,JPEG,TIFF,PNG
    @param mode: 图片模式,默认为RGB
    @param bg_color: 背景顏色,預設為白色
    @param fg_color: 前景色,驗證碼字符顏色,預設為藍色#0000FF
    @param font_size: 驗證碼字體大小
    @param font_type: 驗證碼字體,預設為 ae_AlArabiya.ttf
    @param length: 驗證碼字符個數
    @param draw_lines: 是否畫干擾線
    @param n_lines: 干擾線的條數範圍,格式元组,預設為(1, 2),只有draw_lines为True時有效
    @param draw_points: 是否畫干擾點
    @param point_chance: 干擾點出現的概率,大小范圍[0, 100]
    @return: [0]: PIL Image實例
    @return: [1]: 驗證碼圖片中的字符串
    """
    width, height = size  # 寬高
    # 創建圖形
    img = Image.new(mode, size, get_random_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=get_random_color())

    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 = create_validate_code()
# print(img,strs)
# img.show()

表單中寫入

             <form id="loginform"><input type="text" name="operation" value="login" style="display:none;"/>
              <div class="form-group">
                <label for="user">用戶名</label>
                <input type="text" name="username" class="form-control" id="username"/>
              </div>
              <div class="form-group">
                <label for="user">密碼</label>
                <input type="password" name="password" class="form-control" id="password"/>
              </div>
              <div class="form-group">
                <label for="user">驗證碼</label>
                <div class="row">
                  <div class=col-md-6>
                    <input type="text" name="validcode" class="form-control" id="validcode"/>
                  </div>
                  <div class="col-md-6">
                    <img src="/crm/validimg/" alt="">   #src寫入要讀取驗證碼的URL
                  </div>
                  <span id="code_err" style="color:red;"></span>
                </div>
              </div>
              <div class="btn btn-primary pull-right" id="login_btn">login</div>
            </form>

在django urls.py中寫入

from django.urls import path,re_path
from app import views

urlpatterns = [
    re_path(r'crm/validimg/', views.check_code),

]

view.py 寫入一個驗證碼URL使用的函數

def check_code(request):
    import io
    stream = io.BytesIO()
    #創建隨機字符code
    #創建一張圖片格式的字符串,將隨機字符串寫到圖片上
    img, code = ck.create_validate_code()

    img.save(stream,"png")
    # 將字符串形式的驗證碼放到頁面中
    request.session["CheckCode"] = code
  # 將驗證碼的字符串寫入session中,給後台驗證用
    return HttpResponse(stream.getvalue())

登入的函數

from django.http import JsonResponse
from django.contrib import auth   #使用django內建的驗證組件

# 建立一個回傳訊息的物件類
class BaseResponse(object):
    def __init__(self):
        self.status=True
        self.error=None
        self.data=None

def login(request):
    ret = BaseResponse()
    if request.method == "GET":
        return render(request,'crm/login.html')
    elif request.is_ajax():
        code = request.POST['validcode']
        # 讀取session中的驗證碼數據與輸入的驗證碼做比對
        if request.session.get('CheckCode') == code:
            username = request.POST['username']
            password = request.POST['password']
            # 驗證使用者帳戶密碼是否正確
            user_obj = auth.authenticate(username=username,password=password)
            if user_obj:
                #登入成功後,將登入成功訊息寫入session
                request.session['is_auth'] = True
                request.session['username'] = user_obj.username
            else:
                ret.status = False
                ret.error = "用戶名或密碼錯誤"
        else:
            ret.status = False
            ret.error = "驗證碼錯誤"

        # 使用字典物件回傳訊息,在前台接收字典類型的物件
        return JsonResponse(ret.__dict__)
01-01 06:36