app
from flask import Flask
from flask_script import Manager
from App.views import bp
app = Flask(__name__)
app.config.from_pyfile("settings.py")
manager = Manager(app)
app.register_blueprint(bp)
if __name__ == '__main__':
manager.run()
settings
from datetime import timedelta
SECRET_KEY = "i9490kl*(780990HGjhsoid7872378287mn,,.,ghghY!@3"
PERMANENT_SESSION_LIFETIME = timedelta(days=3)
PERMANENT = True
App.views
from flask import Blueprint,session, make_response,request,render_template,redirect
from App.forms import RegisterForm
from App.verifycode import vc
bp = Blueprint("bp",__name__)
@bp.route("/verify/")
def verify_code():
result = vc.generate()
session['code'] = vc.code
response = make_response(result)
response.headers["Content-Type"] = "image/png"
return response
@bp.route("/register/",methods=['GET','POST'])
def register_user():
form = RegisterForm()
if request.method == 'POST':
if form.validate_on_submit():
print(form)
return redirect('/verify')
return render_template("register.html",**locals())
App.verifycode
import os
from io import BytesIO
from random import randint
from PIL import Image,ImageFont,ImageDraw
class VerifyCode:
def __init__(self,width=100,height=40,size=4):
"""
:param width: 驗證碼圖片寬度
:param height: 高度
:param size: 字符數
"""
self.width = width
self.height = height
self.size = size
self.__code = ''
self.pen = None
@property
def code(self):
return self.__code
def generate(self):
im = Image.new("RGB",(self.width,self.height),self.__rand_color(150))
self.pen = ImageDraw.Draw(im)
self.rand_string()
self.__draw_code()
self.__draw_point()
self.__rand_line()
buf = BytesIO()
im.save(buf,'png')
res = buf.getvalue()
buf.close()
return res
def __rand_color(self,min=0,max=255):
return randint(min,max),randint(min,max),randint(min,max)
def rand_string(self):
self.__code = ''
for i in range(self.size):
self.__code += str(randint(0,9))
def __draw_code(self):
path = os.path.join(os.getcwd(),'static/fonts/SIMLI.TTF')
print(path)
font1 = ImageFont.truetype(path,size=20,encoding="utf-8")
width = (self.width-20) // self.size
for i in range(len(self.__code)):
x = 13 + width * i
self.pen.text((x,9),self.__code[i],font=font1,fill=self.__rand_color(0,80))
def __draw_point(self):
for i in range(100):
self.pen.point((randint(1, self.width-1), randint(1, self.height-1)), self.__rand_color(30,100))
def __rand_line(self):
for i in range(5):
self.pen.line([(randint(1, self.width-1), randint(1, self.height-1)), (randint(1, self.width-1), randint(1, self.height-1))], fill=self.__rand_color(50,150), width=2)
vc = VerifyCode()
App.forms
from flask import session
from flask_wtf import FlaskForm
from wtforms import StringField
from wtforms.validators import ValidationError
class RegisterForm(FlaskForm):
code = StringField()
def validate_code(self,field):
print(field.data ,session.get('code'))
if field.data != session.get('code'):
raise ValidationError("驗證碼匹配失敗")
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="{{ url_for('bp.register_user') }}" method="post">
{{ form.csrf_token }}
<input type="text" name="code">
<img src="{{ url_for('bp.verify_code') }}" alt="" onclick="this.src={{ url_for('bp.verify_code') }}+'?'+Math.random()">
{% for error in form.code.errors %}
<span>{{ error }}</span>
{% endfor %}
<br>
<input type="submit">
</form>
</body>
</html>