Flask框架的学习——11—(WTForms表单验证-常用验证器、文件上传、上传文件名称中文问题、验证上传文件格式)
1、WTForms表单验证
Flask-WTF
Flask-WTF是简化了WTForms操作的一个第三方库。WTForms表单的两个主要功能是验证用户提交数据的合法性以及渲染模板。当然还包括一些其他的功能:CSRF保护,文件上传等。安装Flask-WTF默认也会安装WTForms,因此使用以下命令来安装Flask-WTF。
pip install flask-wtf
安装完Flask-WTF后。来看下第一个功能,就是用表单来做数据验证,现在有一个forms.py文件,然后在里面创建一个RegistForm的注册验证表单.
表单验证–邮箱验证等常用验证器
邮箱验证需要先导入新的库:email_validator
主程序文件app.py
from flask import Flask, request, render_template
from forms import RegistForm # 设置为根目录之后,导入forms.py中的RegistForm进行表单验证app = Flask(__name__)@app.route("/")
def index():return "123"from forms import LoginForm# login 登录验证
@app.route("/login/", methods=['GET', 'POST'])
def login():if request.method == 'GET':return render_template('login.html')else:form = LoginForm(request.form) # 将forms.py中的验证信息都传入form中if form.validate(): # 调用validate方法后,会将form传入forms.py中用RegistForm做个验证return "success"else:# 验证错误信息print(form.errors)print(form.errors.get('captcha')[1]) # 输出错误信息message,可以传回前端进行渲染return "fail"if __name__ == '__main__':app.run(debug=True)
login.html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action="" method="post"><table><!-- 邮箱验证 --><tr><td>邮箱:</td><!-- name="email"必须要和forms.py中的email = StringField(validators=[Email()])一样才能使用 --><td><input type="text" name="email"></td></tr><!-- 年龄验证 --><tr><td>年龄:</td><!-- name="age"必须要和forms.py中的一样才能使用 --><td><input type="text" name="age"></td></tr><!-- 用户名验证 --><tr><td>用户名:</td><td><input type="text" name="username"></td></tr><!-- 手机号验证 --><tr><td>手机号:</td><td><input type="text" name="phone"></td></tr><!-- url验证 --><tr><td>链接:</td><td><input type="text" name="info"></td></tr><!-- 验证码验证 --><tr><td>验证码:</td><td><input type="text" name="captcha"></td></tr><tr><td><input type="submit" value="提交"></td></tr></table></form>
</body>
</html>
验证文件 forms.py
# -*- encoding: utf-8 -*-
"""
@File : forms.py
@Time : 2020/4/29 17:07
@Author : chen"""
from wtforms import Form, StringField, validators, IntegerField, ValidationError
from wtforms.validators import Length, Regexp, EqualTo, Email, number_range, InputRequired, URL
# Regexp 正则表达式模块
# wtforms.validators包含很多内置验证器
# EqualTo 验证器:密码不一致# 表单验证采用wtforms模块class RegistForm(Form):# 实现判断username的长度验证3-10username = StringField(validators=[Length(min=3, max=10, message="用户名长度不正确")])# 判断password的长度验证3-10password = StringField(validators=[Length(min=3, max=10)])# 判断 password_repate 的长度验证3-10 EqualTo("password")验证password_repate是否一致password_repate = StringField(validators=[Length(min=3, max=10), EqualTo("password", message="两次密码不一致")])# 表单验证--新的验证器
class LoginForm(Form):email = StringField(validators=[Email()]) # 注意是方法age = IntegerField(validators=[number_range(3, 120, message="年龄输入有误")]) # 年龄类型是int,number_range(min, max)username = StringField(validators=[InputRequired()]) # InputRequired()必须输入# 手机号验证 正则表达Regexp(r'1[8|3|7]\d{9}')代表 开头是1,第二位数字是[8,3,7]中的一个,\d{9}代表九个数字phone = StringField(validators=[Regexp(r'1[8|3|7]\d{9}')])# 网页链接 URL() 源码中有判断的正则表达式info = StringField(validators=[URL()])# 验证码验证captcha = StringField(validators=[Length(min=4, max=4)])'''# 验证内容 无效写法if captcha == '1234':print("验证码正确")else:print("验证码错误")'''# 验证码内容验证 必须定义一个 validate_+验证名称 的函数进行验证,即validate_captchadef validate_captcha(self, field):print(type(field))print(field)if field.data != '1234':raise ValidationError('验证码错误') # 主动抛出异常
2、文件上传
- 在模版中,form表单中,需要指定encotype='multipart/form-data’才能上传文件。
- 在后台如果想要获取上传的文件,那么应该使用request.files.get(‘avatar’)来获取。
- 保存文件之前,先要使用werkzeug.utils.secure_filename来对上传上来的文件名进行一个过滤。这样才能保证不会有安全问题。
- 获取到上传上来的文件后,使用avatar.save(路径)方法来保存文件。、
- 从服务器上读取文件,应该定义一个url与视图函数,来获取指定的文件。在这个视图函数中,使用send_from_directory(文件的目录,文件名)来获取。
程序主文件flask_upload_demo.py
# -*- encoding: utf-8 -*-
"""
@File : flask_upload_demo.py
@Time : 2020/4/30 20:53
@Author : chen"""
from flask import Flask, render_template, request
import os # 导入文件地址模块app = Flask(__name__)
upload_path = os.path.join(os.path.dirname(__file__), 'images')
print(upload_path) # 'images'文件的绝对路径@app.route('/')
def index():return '123'@app.route("/upload/", methods=['GET', 'POST'])
def upload():# return render_template('upload.html')if request.method == 'GET': # get请求用request.args.get()接收return render_template('upload.html')else:desc = request.form.get('desc') # post请求用request.form.get()接收image_file = request.files.get('image_file') # request.files.get()接收文件类型# image_file.filename 保存文件的名字 对应html中的name="image_file" 'images'保存的文件夹名称image_file.save(os.path.join('images', image_file.filename)) # os.path.join('images', image_file.filename)是两个参数在join()中print(os.path.join('images')) # 'images'文件的路径return '文件上传成功'if __name__ == '__main__':app.run(debug=True)
upload.html文件
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><!-- enctype="multipart/form-data" 文件上传必须要添加的属性 --><form action="" method="post" enctype="multipart/form-data"><table><tr><td>头像</td><td><input type="file" name="image_file"></td></tr><tr><td>描述</td><td><input type="text" name="desc"></td></tr><tr><td><input type="submit" value="上传"></td></tr></table></form></body>
</html>
image_file.filename 保存文件的名字 对应html中的name="image_file"
’images’新创建的保存的文件夹名称
3、上传文件名称中文问题
参考CSDN博主「kler」的博客:https://blog.csdn.net/qq_36390239/article/details/98847888
1、修改源码;
…Python37\Lib\site-packages\werkzeug\utils.py,找到secure_filename(filename)函数。
修改secure_filename(filename)函数源码后
if isinstance(filename, text_type):from unicodedata import normalizefilename = normalize('NFKD', filename).encode('utf-8', 'ignore') # 转码if not PY2:filename = filename.decode('utf-8') # 解码for sep in os.path.sep, os.path.altsep:if sep:filename = filename.replace(sep, ' ')# myself define # 正则增加对汉字的过滤# \u4E00-\u9FBF 中文
#构建新正则_filename_ascii_add_strip_re = re.compile(r'[^A-Za-z0-9_\u4E00-\u9FBF.-]')# 使用正则filename = str(_filename_ascii_add_strip_re.sub('', '_'.join( filename.split()))).strip('._')
2、使用第三方库(pypinyin),将中文名转换成拼音;
from pypinyin import lazy_pinyin
filename = secure_filename(''.join(lazy_pinyin(file.filename)))
3、使用uuid模块重命名文件名
python的uuid模块提供UUID类和函数uuid1(), uuid3(), uuid4(), uuid5() 来生成1, 3, 4, 5各个版本的UUID
( 需要注意的是: python中没有uuid2()这个函数)。
a) uuid.uuid1([node[, clock_seq]]) : 基于时间戳使用主机ID, 序列号, 和当前时间来生成UUID, 可保证全球范围的唯一性. 但由于使用该方法生成的UUID中包含有主机的网络地址, 因此可能危及隐私. 该函数有两个参数, 如果 node 参数未指定, 系统将会自动调用 getnode() 函数来获取主机的硬件地址. 如果 clock_seq 参数未指定系统会使用一个随机产生的14位序列号来代替. b) uuid.uuid3(namespace, name) : 基于名字的MD5散列值通过计算命名空间和名字的MD5散列值来生成UUID, 可以保证同一命名空间中不同名字的唯一性和不同命名空间的唯一性,但同一命名空间的同一名字生成的UUID相同.c) uuid.uuid4() : 基于随机数通过随机数来生成UUID. 使用的是伪随机数有一定的重复概率. d) uuid.uuid5(namespace, name) : 基于名字的SHA-1散列值通过计算命名空间和名字的SHA-1散列值来生成UUID, 算法与 uuid.uuid3() 相同.
4、验证上传文件格式
验证代码forms.py
# -*- encoding: utf-8 -*-
"""
@File : forms.py
@Time : 2020/5/1 14:15
@Author : chen"""
from wtforms import Form, FileField, StringField
from flask_wtf.file import FileAllowed, FileRequired
from wtforms.validators import InputRequired# 验证传输文件的类型
class UploadForm(Form):# FileRequired()文件必须上传 FileAllowed(['jpg', 'png', 'gif'])允许接收的文件类型image_file = FileField(validators=[FileRequired(), FileAllowed(['jpg', 'png', 'gif'])])desc = StringField(validators=[InputRequired()])
主程序文件flask_upload_demo.py
# -*- encoding: utf-8 -*-
"""
@File : flask_upload_demo.py
@Time : 2020/4/30 20:53
@Author : chen"""
from flask import Flask, render_template, request, send_from_directory # send_from_directory 通过路由访问上传的文件
import os # 导入文件地址模块
from werkzeug.utils import secure_filename # 上传文件中文问题解决
from forms import UploadForm # 导入文件的类型判断验证from werkzeug.datastructures import CombinedMultiDict # 合并参数进行传递app = Flask(__name__)
upload_path = os.path.join(os.path.dirname(__file__), 'images')
print(upload_path) # 'images'文件的绝对路径@app.route('/')
def index():return '123'@app.route("/upload/", methods=['GET', 'POST'])
def upload():# return render_template('upload.html')if request.method == 'GET': # get请求用request.args.get()接收return render_template('upload.html')else:'''desc = request.form.get('desc') # post请求用request.form.get()接收image_file = request.files.get('image_file') # request.files.get()接收文件类型# 转换文件名称,中文的问题filename = secure_filename(image_file.filename)# image_file.filename 保存文件的名字 对应html中的name="image_file" 'images'保存的文件夹名称image_file.save(os.path.join('images', filename)) # os.path.join('images', image_file.filename)是两个参数在join()中print(os.path.join('images')) # 'images'文件的路径'''# 验证上传文件类型form = UploadForm(CombinedMultiDict([request.form, request.files]))if form.validate():# desc = request.form.get('desc') # post请求用request.form.get()接收# image_file = request.files.get('image_file') # request.files.get()接收文件类型# 简化写法,功能与上面相同desc = form.desc.dataimage_file = form.image_file.data# 转换文件名称,中文的问题filename = secure_filename(image_file.filename)image_file.save(os.path.join('images', filename)) # os.path.join('images', image_file.filename)是两个参数在join()中return '文件上传成功'else:print(form.errors) # 输出错误信息return '文件上传失败'# 通过路由访问上传的文件
@app.route("/image/<filename>")
def get_image(filename):return send_from_directory('images', filename) # 'images'文件夹名称,filename文件名称if __name__ == '__main__':app.run(debug=True)
注意:
通过路由访问上传的文件
# 通过路由访问上传的文件
@app.route("/image/<filename>")
def get_image(filename):return send_from_directory('images', filename) # 'images'文件夹名称,filename文件名称
Flask框架的学习——11—(WTForms表单验证-常用验证器、文件上传、上传文件名称中文问题、验证上传文件格式)相关推荐
- Web后端学习笔记 Flask(8) WTForms 表单验证,文件上传
Flask-WTF是简化了WTForms操作的一个第三方库.WTForms表单的两个主要功能是验证用户提交数据的合法性以及渲染模板.同时还包含一些其他的功能.例如CSRF保护,文件上传等功能,安装fl ...
- python表单提交的两种方式_Flask框架学习笔记之表单基础介绍与表单提交方式
本文实例讲述了Flask框架学习笔记之表单基础介绍与表单提交方式.分享给大家供大家参考,具体如下: 表单介绍 表单是HTML页面中负责数据采集功能的部件.由表单标签,表单域和表单按钮组成.通过表单,将 ...
- ASP.NET MVC 2 学习笔记二: 表单的灵活提交
ASP.NET MVC 2 学习笔记二: 表单的灵活提交 前面说到有做到公司内部的一个请假系统,用的是ASP.NET MVC 2+Entity Framework.虽然EF(Entity Frame ...
- flask基础十四之wtf表单
Web表单 Web 表单是 Web 应用程序的基本功能. 它是HTML页面中负责数据采集的部件.表单有三个部分组成:表单标签.表单域.表单按钮.表单允许用户输入数据,负责HTML页面数据采集,通过表单 ...
- HTML5学习系列之表单与文件
article元素 article元素代表文档.页面或应用程序中独立的.完整的.可以独自被外部引用的内容.它可以是一篇博客或报刊中的文章.一篇论坛帖子.一段用户评论或独立的插件,或者其他任何独立的内容 ...
- wtforms表单验证
wtforms表单的两个主要功能是验证用户提交数据的合法性以及渲染模板.安装wtforms的命令为:pip install wtforms. 如下是表单来做数据验证: import wtforms f ...
- 基于VUE的ElementUi可视化表单设计器布局器
码农苦码农懂的个人空间 工作日志 正文 基于VUE的ElementUi可视化表单设计器布局器 顶 原 码农苦码农懂 发布于 09/11 15:35 字数 1187 阅读 41 收藏 0 点赞 1 评论 ...
- html表单的常用属性有哪些,html/form表单常用属性认识
1.form表单常用属性练习 .form1 { margin: auto; height: 900px; width: 500px; text-align: center; line-height: ...
- H5学习笔记(表单、框架)
表单标签 表单用于收集不同类型的用户输入数据 form常用属性 form标签定义表单 属性名 代码 描述 action <form action ="服务器地址">&l ...
- Selenium自动化测试框架基础学习(元素表单操作)(Selenium操作)
目录 一.Selenium自动化测试框架 1.1什么是框架? 1.2为什么使用框架? 1.3Selenium-webdriver工作原理 1.4selenium环境搭建(详情查阅讲义) 1.5什么是S ...
最新文章
- 如何在AxureRP7中使用FontAwesome字体
- 【USACO 3.1】Score Inflation(完全背包)
- lisp pl线线段数_vlisp每日源码(标注多段线线长)
- mysql.net开发驱动_mysql数据库.net开发驱动(mysql connector net )
- 利用js实现popup弹窗
- 副主任护师主要英语和计算机吗,有没有晋升副主任护师的
- 正则环视 php,正则表达式基本知识(php)
- Magento站点优化方案
- 2021-2025年中国单相静态电能表行业市场供需与战略研究报告
- opencv手册_OpenCV之单目测距实现
- 计算机三位科学家,华南理工大学这三位年轻科学家太优秀了!
- zookeeper + dubbo 搭建
- 谈ISO9000-3内容及其与CMM关系
- 谷歌浏览器Chrome播放rtsp视频流解决方案
- win10设置中账户点开闪退问题
- android标题栏尺寸,Android平台设计规范19条(轻松入门)
- oracle数据库小记
- 惯性导航的定位原理是什么?
- arm 中的nor flash 和 nand flash
- 如何搭建一个好的知识库管理系统?
热门文章
- pytorch 学习笔记 part14 过拟合欠拟合及解决方案
- 秃头程序员保姆教程:Spring框架自学之路(一)
- Clonezilla 再生龙制作系统U盘还原系统
- 每日单词20110606
- 第十一届蓝桥杯 2020年省赛真题 (C/C++ 大学A组) 第一场
- 在html中做框架的页面,网页中的框架(详解)
- 伍斯特理工学院计算机科学硕士,美国伍斯特理工学院数据科学硕士录取
- 各大主流编程语言比较,运用场景
- 10247: 爱好数学的国王(唯一分解定理)
- 计算机打字声音,键盘打字声音在哪设置