当前位置:网站首页>Flask框架——Flask-WTF表单:文件上传、验证码
Flask框架——Flask-WTF表单:文件上传、验证码
2022-07-25 09:50:00 【白巧克力LIN】
目录
在上篇文章中,我们学习了Flask框架——Flask-WTF表单:数据验证、CSRF保护,这篇文章我们学习Flask框架——Flask-WTF表单:文件上传、验证码。
文件上传
Flask-WTF表单提供FileField字段来处理文件上传,它在表单提交后,自动从flask.request.files中抽取数据。
示例代码如下所示:
import os
from flask import Flask, render_template
from flask_wtf import FlaskForm, CSRFProtect
from flask_wtf.file import FileField, FileRequired, FileAllowed
app = Flask(__name__)
app.config['SECRET_KEY']='hakhfaskh' #配置CSRF需要的密钥,其值是任意的
csrf = CSRFProtect(app) #将CSRF保护加入到app中
class Myform(FlaskForm):
file = FileField(label='用户头像上传',validators=[FileRequired(), FileAllowed(['jpg','png'])]) #创建FileField字段
@app.route('/',methods=['GET','POST'])
def hello_world():
myform = Myform() #创建表单对象
if myform.validate_on_submit(): #检查是否是一个POST请求并且请求是否有效
filename=myform.file.data.filename #获取传入的文件名
filepath=os.path.dirname(os.path.abspath(__file__)) #获取当前项目的文件路径
savepath=os.path.join(filepath,'static') #设置保存文件路径
myform.file.data.save(os.path.join(savepath,filename)) #保存文件
return '提交成功'
return render_template('file.html', myform=myform) #使用render_template()方法渲染file.html文件并将myform传递到file.html中
if __name__ == '__main__':
app.run(debug=True)
配置CSRF需要的密钥并将CSRF保护加入到app中,然后创建名为Myform的表单类,在类中我们定义了FileField文件字段并使用了FileRequired文件验证函数和FileAllowed文件类型验证函数。
在视图函数中创建表单类对象,使用了validate_on_submit()方法检查是否是一个POST请求并且请求是否有效,获取传入的文件名并定义保存文件的路径,最后使用render_template()方法渲染file.html文件并将myform传递到file.html中。
创建名为file.html文件,其内容如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="{
{ url_for('hello_world') }}" method="post" enctype="multipart/form-data">
{
{ myform.csrf_token }} {#渲染csrf#}
<p>{
{ myform.file.label }}{
{ myform.file }}</p>
<input type="submit" value="提交">
</form>
</body>
</html>
注意:涉及到文件相关的,需要在 HTML 表单的 enctype 设置成 multipart/form-data。
启动flask项目,访问http://127.0.0.1:5000/并选择文件,如下图所示:

验证码
Flask-WTF 通过 RecaptchaField 也提供对验证码的支持,示例代码如下:
from flask import Flask, render_template
from flask_wtf import FlaskForm, RecaptchaField, CSRFProtect
app = Flask(__name__)
app.config['SECRET_KEY']='hakhfaskh' #配置CSRF需要的密钥,其值是任意的
csrf = CSRFProtect(app) #将CSRF保护加入到app中
class Myform(FlaskForm):
recaptcha = RecaptchaField() #验证码字段
@app.route('/')
def yanzm():
myform=Myform() #创建表单对象
return render_template('yanzm.html', myform=myform) #使用render_template()方法渲染yanzm.html文件并将myform传递到file.html中
if __name__ == '__main__':
app.run()
配置CSRF需要的密钥并将CSRF保护加入到app中,创建名为Myform的表单类,在类中我们定义了RecaptchaField验证码字段,在视图函数中我们创建表单对象,使用render_template()方法渲染yanzm.html文件并将myform传递到file.html中。
使用验证码还需要配置如下参数:
RECAPTCHA_PUBLIC_KEY:必选,公钥;
RECAPTCHA_PRIVATE_KEY:必选,私钥;
RECAPTCHA_API_SERVER:可选,验证码API服务器;
RECAPTCHA_PARAMETERS:可选,一个JavaScript(api.js)参数的字典;
RECAPTCHA_DATA_ATTRS:可选,一个数据属性项列表 https://developers.google.com/recaptcha/docs/display。
创建名为yanzm.html,其内容如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/" method="post">
{
{ myform.csrf_token }}
{
{ myform.recaptcha }}
</form>
</body>
</html>
启动flask项目,访问http://127.0.0.1:5000/,发现什么都没显示,这是因为RecaptchaField()字段需要调用谷歌的验证码API,而调用谷歌的验证码API需要翻墙,我们没有翻墙,所以什么都没显示,如下图所示:

使用RecaptchaField()验证码字段需要翻墙,那么我们就不使用它,我们自己绘制验证码。
这里我们绘制验证码使用pillow图形库,其执行如下代码安装:
pip install pillow
安装好pillow后,我们创建一个名为uitl.py文件,其作用是绘制我们的图形验证码,代码如下:
import random
from PIL import Image, ImageFont, ImageDraw
#自定义get_color方法,获取三位随机数并保存在元组中
def get_color():
return (random.randint(0,255),random.randint(0,255),random.randint(0,255))
#自定义generate_image方法绘制图片验证码
def generate_image(4):
size=(130,50) #设置验证码的大小
im=Image.new('RGB',size,color=get_random_color()) #创建验证码背景图
font=ImageFont.truetype('C:\Windows\Fonts/simsun.ttc',size=40) #设置验证码字体
draw=ImageDraw.Draw(im) #创建ImageDraw对象
code='' #设置验证码值
s='abcdefghijklmnopqrstuvwxyz123456' #设置验证码的取值范围
for i in range(4): #绘制4位数验证码值
c=random.choice(s) #随机在s中取值
code+=c #将取到的值放在验证码中
draw.text((9+random.randint(4,7)+20*i,random.randint(4,7)),text=c,fill=get_random_color(),font=font) #在验证码背景图中写入验证码值
im.show()
return im ,code #返回图片和验证码值
我们自定义get_color方法获取三位随机数保存在元组并返回,再自定义generate_image()方法绘制图片验证码,设置验证码的取值范围、背景图大小字体等,并随机获取验证码值写入验证码背景图中。
大家可以根据pillow库的文档来为验证码增加一些干扰线,这样简易版的图形验证码就制作完毕了,如下图所示:

这里我们是绘制了4个字符的图片验证码,图片验证码代码生成已经写好了,接下来我们编写flask项目来使用验证码,示例代码如下所示:
from flask import Flask, render_template, session
from flask_wtf import FlaskForm, CSRFProtect
from wtforms import StringField, ValidationError
app = Flask(__name__)
app.config['SECRET_KEY']='hakhfaskh' #配置CSRF需要的密钥,其值是任意的
csrf = CSRFProtect(app) #将CSRF保护加入到app中
class Myform(FlaskForm): #创建表单类
recaptcha = StringField() #创建文本字段
def validate_recaptcha(self, data): #自定义验证
input_code=data.data #输入的验证码的值
code=session.get('valid') #获取session的valid值
if input_code.lower()!=code.lower(): #验证码值转换为小写并判断输入的验证码和图片验证码值是否一致
raise ValidationError('验证码错误') #抛出错误
@app.route('/',methods=['GET','POST'])
def yanzm():
myform=Myform() #创建表单类对象
if myform.validate_on_submit(): #检查是否是一个POST请求并且请求是否有效
return '验证成功'
return render_template('yanzm.html', myform=myform) #使用render_template()方法渲染yanzm.html文件并将myform传递到file.html中
if __name__ == '__main__':
app.run()
设置CSRF保护,创建表单类使用StringField()文本字段并自定义验证函数,然后在视图函数中创建表单类对象,使用validate_on_submit()方法检查是否是一个POST请求并且请求是否有效,使用render_template()方法渲染yanzm.html文件并将myform传递到file.html中。
是不是这样就可以了呢?这里我们还需要创建一个视图函数来获取图片验证码,代码如下所示:
from util import generate_image #导入刚才编写的绘制验证码中的generate_image
@app.route('/image')
def get_image():
im,code=generate_image() #获取验证码图片与值
buffer=BytesIO() #将image对象转成二进制
im.save(buffer,"JPEG") #以二进制形式保存为JPEG格式
buf_bytes=buffer.getvalue() #读取二进制验证码
session['valid']=code #保存到session中,控制验证码的失效时间
response=make_response(buf_bytes) #构造response对象
response.headers['Content-Type']='image/jpg' #定制请求头
return response
在视图函数中,我们通过调用generate_image()方法来获取验证码图片与值并将图片以二进制形式保存为JPEG格式,由于一般情况下验证码是有失效时间的,所以我们使用session控制验证码的实现时间,使用make_response()构造response对象为验证码图片定制请求头。
接下来我们编写yanzm.html文件,代码如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/" method="post">
{
{ myform.csrf_token }} {#渲染csrf#}
{
{ myform.recaptcha }}<img src="{
{ url_for('get_image') }}" alt="" id="img">
<p>{
{ myform.recaptcha.errors.0 }}</p>
<input type="submit" value="提交">
</form>
</body>
</html>
一般情况下,只要我们点击图片验证码就会刷新,所以我们可以加入以下代码来控制图片验证码的刷新:
<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
<script>
$('#img').click(function (){
$(this).attr('src',"{
{ url_for('get_image') }}?ran="+Math.random());
})
</script>
这里我们调用了百度的jquery并为验证码添加了点击事件。
好了,这样就成功绘制了我们的图片验证码了,启动flask项目,访问http://127.0.0.1:5000/,如下图所示:

当我们正确输入时并点击提交,就会显示验证成功,当我们错误输入并点击提交,就会显示验证码错误。
好了,Flask框架——Flask-WTF表单:文件上传、验证码就讲到这里了,感谢观看,下篇文章学习Flask框架——Flask-Mail邮件。
公众号:白巧克力LIN
该公众号发布Python、数据库、Linux、Flask、自动化测试、Git等相关文章!
- END -
边栏推荐
- 2021 牛客网笔试总结 01
- Multithreading - static proxy mode
- The practice of asynchronous servlet in image service
- 存储、计算、分布式存储篇(收集整理适合小白)
- 5. NFS shared services and SSH Remote Control Services
- Gan, why '𠮷 𠮷'.Length== 3 ??
- 4、 Testfixture test fixture, or test firmware
- Test plan and test plan
- 信号完整性(SI)电源完整性(PI)学习笔记(三十三)102条使信号完整性问题最小化的通用设计规则
- UE4 window control (maximize minimize)
猜你喜欢

HCIP实验(04)

The idea has been perfectly verified again! The interest rate hike is approaching, and the trend is clear. Take advantage of this wave of market!

【蓝桥杯集训100题】scratch太极图 蓝桥杯scratch比赛专项预测编程题 集训模拟练习题第22题

4.FTP服务配置与原理

4. FTP service configuration and principle

HCIP实验(02)

Angr (VII) -- angr_ ctf

2021 CEC笔试总结

js 双向链表 02

Attention is all you need paper intensive reading notes transformer
随机推荐
Pytorch calculates the loss for each sample in the batch
Hucang integrated e-commerce project (II): project use technology, version and basic environment preparation
Vs Code connects to the remote jupyter server
What is the meaning of ordinary people's life?
The practice of asynchronous servlet in image service
Keras deep learning practice (16) -- detailed explanation of self encoder
电磁场与电磁波实验一 熟悉Matlab软件在电磁场领域的应用
ESP32C3基于Arduino框架下的 ESP32 RainMaker开发示例教程
7.shell实用的小工具cut等
Electromagnetic field and electromagnetic wave experiment I familiar with the application of MATLAB software in the field of electromagnetic field
Analysis of event channel principle in Kraken
Introduction to onnx runtime
User preferences
HCIA实验(08)
After switching the shell command line terminal (bash/zsh), CONDA cannot be used: command not found
AI技术栈太庞大!吴恩达给出职业生涯规划:终生学习
UE4 external open EXE file
Angr (x) - official document (Part1)
Upgrade glibc 2.29 checking LD_ LIBRARY_ Path variable... Contains current directory error solution
微信小程序WxPrase中包含文件无法点击解决