需要导入字体插件:
from PIL import Image,ImageDraw,ImageFont,ImageFilter import random def rd_check_code(width=120, height=30, char_length=5, font_file='kumo.ttf', font_size=28): code = [] img = Image.new(mode='RGB', size=(width, height), color=(255, 255, 255)) draw = ImageDraw.Draw(img, mode='RGB') def rndChar(): """ 生成随机字母 :return: """ return chr(random.randint(65, 90)) def rndColor(): """ 生成随机颜色 :return: """ return (random.randint(0, 255), random.randint(10, 255), random.randint(64, 255)) # 写文字 font = ImageFont.truetype(font_file, font_size) for i in range(char_length): char = rndChar() code.append(char) h = random.randint(0, 4) draw.text([i * width / char_length, h], char, font=font, fill=rndColor()) # 写干扰点 for i in range(40): draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor()) # 写干扰圆圈 for i in range(40): draw.point([random.randint(0, width), random.randint(0, height)], fill=rndColor()) x = random.randint(0, width) y = random.randint(0, height) draw.arc((x, y, x + 4, y + 4), 0, 90, fill=rndColor()) # 画干扰线 for i in range(5): x1 = random.randint(0, width) y1 = random.randint(0, height) x2 = random.randint(0, width) y2 = random.randint(0, height) draw.line((x1, y1, x2, y2), fill=rndColor()) img = img.filter(ImageFilter.EDGE_ENHANCE_MORE) return img,''.join(code)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <link rel="stylesheet" href="/static/plugins/bootstrap-3.3.7-dist/css/bootstrap.css"> <link rel="stylesheet" href="/static/plugins/font-awesome-4.7.0/css/font-awesome.css"> <style> .login { 600px; margin: 0 auto; padding: 20px; margin-top: 80px; } </style> </head> <body> <div class="login"> <form class="form-horizontal" action="/login.html" method="POST"> {% csrf_token %} <div class="form-group"> <label class="col-sm-2 control-label">用户名</label> <div class="col-sm-10"> <p>{{ obj.username }}{{ obj.errors.username.0 }}{{ value_error }}</p> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">密码</label> <div class="col-sm-10"> <p>{{ obj.password }}{{ obj.errors.password.0 }}{{ value_error }}</p> </div> </div> <div class="form-group"> <label class="col-sm-2 control-label">验证码</label> <div class="col-sm-5"> <p><input type="text" class="form-control" placeholder="验证码" name="code">{{ code_error }}</p> </div> <div class="col-sm-5"> <img style=" 120px;height: 30px;" src="/check_code.html"> </div> </div> <div class="form-group"> <div class="col-sm-offset-2 col-sm-10"> <input type="submit" class="btn btn-default" value="登录"> </div> </div> </form> </div> </body> </html>
from django.shortcuts import render, HttpResponse,redirect from app01 import models from django.forms import Form from django.forms import fields from django.forms import widgets import os from django.core.exceptions import ValidationError class LoginForm(Form): """ 登录表单 """ username = fields.CharField( max_length=18, min_length=3, required=True, widget=widgets.TextInput(attrs={'class': 'form-control','placeholder':'用户名','name':"username"}), error_messages={ 'required': "用户名不能为空", 'min_length': '太短了', 'max_length': '太长了', } ) password = fields.CharField( max_length=18, min_length=3, required=True, widget=widgets.PasswordInput(attrs={'class': 'form-control','placeholder':'密码','name':"password"}), error_messages={ 'required': "密码不能为空", 'min_length': '太短了', 'max_length': '太长了', } ) def login(request): """ 登录 :param request: :return: """ if request.method == 'GET': obj = LoginForm() return render(request, 'login.html', {'obj':obj}) else: client_code = request.POST.get('code') server_code = request.session.get('code') obj = LoginForm(request.POST) if client_code != server_code: return render(request, 'login.html', {'code_error': '验证码错误', 'obj':obj}) elif obj.is_valid(): if models.UserInfo.objects.filter(**obj.cleaned_data).first(): request.session['username'] = obj.cleaned_data['username'] return redirect('/all/') else: return render(request, 'login.html', {'value_error': '用户名或者密码错误'}) return render(request, 'login.html', {'obj', obj}) def check_code(request): """ 验证码 :param request: :return: """ from io import BytesIO from utils.random_check_code import rd_check_code img, code = rd_check_code() stream = BytesIO() img.save(stream, 'png') request.session['code'] = code return HttpResponse(stream.getvalue())