web表单
在了解了 Flask Bootstrap 基本框架之后,我们来了解一下 Flask 框架的 表单( form ),以帮助我们创建交互式的 Web 应用,最后会有个提交个人信息的例子。
Flask-WTF 是 Flask 框架的一个扩展,用来做表单的交互,是对 WTForms 的集成,默认支持 CSRF 安全签名,并且继承文件上传功能。
安装
使用 pip 安装
pip install Flask-WTF
验证
>>> from flask_wtf import FlaskForm>>>
小试牛刀
创建表单类
Flask-WTF 能将 WTForms 集成到 Flask 应用中,创建一个 app.py 主代码文件,例如:
from flask_wtf import FlaskFormfrom wtforms import StringFieldfrom wtforms.validators import DataRequiredclass MyForm(FlaskForm):name = StringField('name', validators=[DataRequired()])
MyForm 是自定义的类,继承自 FlaskForm,其中定义了一个字段 name,标题是 name, 且设置为非空。
表单模板
接下来创建一个表单模板 submit.html,例如:
<form method="POST" action="/">{{ form.csrf_token }}{{ form.name.label }} {{ form.name(size=20) }}<input type="submit" value="Go"></form>
其中 form.csrf_token 是 Flask-WTF 提供的一个防止跨站请求伪造的隐藏字段。原理是将一个密钥根据请求特征加密,在表单提交时一起送到服务器端,作校验。
密钥串与多种定义方式,为了方便,这里将密钥串定义在应用上:
app.secret_key = 'abc'
注意:上示例仅作演示说明,不能在生产系统中用这样简单的密钥
之后则是对字段 name 的模板定义,经过渲染会替换成 Html 控件。
定义视图函数
视图函数首先需要将表单渲染出来,另外要对表单的提交作验证,当然视图函数与提交验证函数也可不是同一个:
@app.route('/', methods=('GET', 'POST'))def submit():form = MyForm()if form.validate_on_submit():return redirect('/success')return render_template('submit.html', form=form)
提交表单一般都是 POST 方法,所以要确保视图函数支持 POST
视图函数中实例化一个 MyForm,值得注意的时,FlaskForm 示例化时会使用 request 中的 form 来初始化,所以在下面才可以直接来校验表单
validate_on_submit 方法是 is_submitted 和 validate 的联合校验,后面会详述
如果验证通过将跳转到 /success,如果没有通过,用 form 来渲染 submit.html 模板,
运行
在主代码 app.py 中加入启动方法:
if __name__ == '__main__':app.run(debug=True)
然后运行,如果一起正常,访问 localhost:5000, 就能看输入框和提交按钮,点击提交,会跳转到 /success 或者提升必填。
表单
FlaskForm 是 WTForms Form 的子类,可以用来定一个表单,定义表单中的字段,验证方式等,作为一个 Flask 和 Html 之间的一个数据载体。
另外 FlaskForm 集成了 CSRF 校验,方便编写程序的同时,提高访问安全性。定义 Form 对象时不用明确声明 CSRF 字段,只需要在表单模板中填写 form.csrf_token 就行,提交表单时,视图函数会自动对 CSRF 进行校验。
FlaskForm 实例化参数中有个 formdata 参数,用来设定 Form 中字段的值,在视图函数中,可以不提供 formdata,会将 request.form 或者 request.files 中获取,作为 formdata 参数,这就是视图函数中实例化 Form 时,不带任何参数,在后面还能方法 Form 对象内容的原因。
字段及验证
FlaskForm 从 0.9.0 版本开始,不再从 WTForms 中导入任何东西,所以大部分字段和校验方法都直接引用自 WTForms,如:
from wtforms import StringField, IntergreField, validators
-
常用的字段
| 字段 | 说明 |
|---|---|
| StringField | 文本字段 |
| IntergreField | 文本字段,要求输入的时数字 |
| PasswordField | 文本字段,输入内容会转会为小黑点 |
| DateField | 文本字段,输入指定日期格式的字符串会转会为日期类型 |
| RadioField | 单选字段 |
| SelectField | 选择字段 |
| SelectMultipleField | 多项选择字段 |
| SubmitField | 表单的提交按钮 |
-
常用验证
| 验证 | 说明 |
|---|---|
| DataRequired | 必填字段 |
| 电子邮箱地址验证 | |
| EqualTo | 验证与其他指定字段值是否相等 |
| Length | 输入字符串长度限制 |
| NumberRange | 输入数值大小限制 |
| URL | 网站格式验证 |
例如定义一个 MyForm 表单类:
class MyForm(FlaskForm):name = StringField(label='姓名', validators=[InputRequired()])city = StringField('城市', validators=[validators.Length(min=4, max=25, message='输入的长度不符合要求')])birthday = DateField(label='生日', format="%Y-%m-%d", validators=[DataRequired('日期格式不正确')])gender = RadioField(label='性别', choices=[(1, 'male'), (2, 'female')])interest = SelectMultipleField(label='兴趣', choices=[(1, 'Football'), (2, 'Movies'), (3, 'Reading')])
如果字段值验证失败,会将错误信息存放在字段的 errors 属性中,errors 是个列表,元素是每一个验证出现的问题信息,通过设定验证的 message 参数指定。
要完整的在模板中定义字段以及错误信息,是件乏味的事情,这里通过一个自定义的模板宏来完成:
{% macro render_field(field) %}<dt>{{ field.label }}:<dd>{{ field(**kwargs)|safe }}{% if field.errors %}<ul class=errors>{% for error in field.errors %}<li>{{ error }}</li>{% endfor %}</ul>{% endif %}</dd>{% endmacro %}
文件上传
上传文件,是表单应用必不可少的,可以通过 FileField 字段来设置,因为需要视图函数对上传的文件进行处理,所以这里单独作说明
定义一个有上传文件字段的表单类:
from flask_wtf.file import FileFieldclass PhotoForm(FlaskForm):photo = FileField('上传照片')
视图函数定义为:
@app.route('/upload', methods=['GET', 'POST'])def upload():form = PhotoForm()filepath = Noneif form.validate_on_submit():filename = secure_filename(form.photo.data.filename)file = form.photo.datafilepath = os.path.join(app.config['UPLOAD_FOLDER'], filename)file.save( filepath )else:filename = Nonereturn render_template('photo.html', form=form, filename= filename)
在通过验证之后,用方法 secure_filename 对上传文件名作安全处理,这是很有必要的,以防止通过文件名注入, 这个方法从库 werkzeug 中导入,这个库会在在安装 Flask 时一起被安装。
之后拿到上传文件的数据,这是已经经过 Flask 转化的 File 对象,可以直接调用 save 方法存储上传的文件。
app.config['UPLOAD_FOLDER'] 定义了文件存储的位置,如:
app.config['UPLOAD_FOLDER'] = './upload'
完整的photoupload.py文件:
import osfrom flask import Flask, render_template
from flask_bootstrap import Bootstrap
from flask_wtf import FlaskForm
from flask_wtf.file import FileField
from werkzeug.utils import secure_filenameclass PhotoForm(FlaskForm):photo = FileField('上传照片')app = Flask(__name__)
app.secret_key = 'abc'
app.config['UPLOAD_FOLDER'] = './upload'
bootstrap = Bootstrap(app)@app.route('/upload', methods=['GET','POST'])
def upload():form = PhotoForm()filepath = Noneif form.validate_on_submit():filename = secure_filename(form.photo.data.filename)file = form.photo.datafilepath = os.path.join(app.config['UPLOAD_FOLDER'],filename)file.save(filepath)else:filename = Nonereturn render_template('upload.html', form = form,filename=filename)if __name__ == '__main__':app.run()
最后新建一个模板文件 upload.html:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body><form action = "/upload" method = "post" enctype="multipart/form-data">{{ form.csrf_token() }}{{ form.photo() }}<input type = "submit" value = "提交"></form>
</body>
</html>
注意模板中 form 的编码类型必须设置为 multipart/form-data
Bootstrap
虽然 FlaskForm 使用起来已经很方便了,但是还是有很多需要重复编写的地方,以及展示效果不够美观的问题,借助 Bootstrap-flask 将解决这些问题。
之前对 Bootstrap-flask 介绍中说国,Bootstrap-flask 主要是定义了很多模板宏,减少重复的编码,对于表单,同样提供了很多宏
首先在模板中导入 bootstrap 的 Form 相关宏:
{% from 'bootstrap/form.html' import render_form, render_form_row, render_field %}
-
render_form接受一个 Form 对象,将其渲染成 Html 表单,是最省事的,例如:
{{ render_form(form) }}
-
render_field接受一个 Field, 将其渲染成一个表单的字段:
{{ render_field(form.name) }}
-
render_form_row接受一个 Field 列表,将列表中的字段渲染到一行
模板代码如下:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title>
</head>
<body>
{% extends 'bootstrap/base.html' %}
{% from 'bootstrap/form.html' import render_form, render_form_row, render_field %}
{{ bootstrap.load_css() }}
<h1> render_form </h1>
{{ render_form(form) }}<h1>render_form_row</h1>
<form method="post" >{{ render_form_row([form.name, form.city]) }}{{ render_form_row([form.gender, form.birthday]) }}{{ render_form_row([form.interest]) }}
</form><h1>render_field</h1>
<form method="post" >{{ render_field(form.name) }}{{ render_field(form.gender) }}{{ render_field(form.interest) }}
</form>
</body>
</html>
问题:jinja2.exceptions.TemplateNotFound: bootstrap/form.html
先导入表单相关的宏,然后加入 Bootstrap 的样式,之后是各个宏的使用
总结
本节课程简单介绍了 Flask 中表单的处理方式和方法,包括 FlaskForm,WTForms和一些常用的字段,最后说明了 Bootstrap-flask 对表单的支持,以便是 Web 开发更高效。
相关文章:
web表单
在了解了 Flask Bootstrap 基本框架之后,我们来了解一下 Flask 框架的 表单( form ),以帮助我们创建交互式的 Web 应用,最后会有个提交个人信息的例子。 Flask-WTF 是 Flask 框架的一个扩展,用来做表单的交互,是对 WT…...
C++BUG记录:文件无法创建,文件路径正确但使用了Format
问题1:xx.Format()不存在与参数列表匹配的重载函数 问题:文件的路径名字是通过Format转换组合而成的,会报错“FileName.Format()不存在与参数列表匹配的重载函数”。 FileName.Format("%s%d", FilePath, num);//报错:…...
nodejs框架 express koa介绍以及从零搭建 koa 模板
express 下载 npm install express搭建服务 const express require("express");const app express();app.get("/home", (req, res) > {res.send("home"); });app.listen(3000, () > {console.log("http://127.0.0.1:3000")…...
84 | Python可视化篇 —— Pyecharts数据可视化
文章目录 1. 简介安装和环境设置2. 基本图表类型折线图(Line Chart)散点图(Scatter Plot)柱状图(Bar Chart)饼图(Pie Chart)地理地图(Geo Map)3. 数据处理和图表配置4. 高级图表类型5. 自定义选项和交互性6. 数据可视化和动态图7. 组合图表和多子图1. 简介 Pyechart…...
【Nginx】Nginx负载均衡
负载均衡:通过反向代理来实现 Nginx的七层代理和四层代理: 七层是最常用的反向代理方式,只能配置在nginx配置文件的http模块当中 ;配置的方法名称为:upstream模块,不能写在server中也不能写在location中&a…...
vue3报错
这是因为eslint对代码的要求严格导致的,可以在package.json里面删掉"eslint:recommended",然后重启就可以正常运行了...
每日一学——IP地址和子网掩码
IP地址和子网掩码是网络中非常重要的概念。IP地址是用于标识和寻址网络中设备(如计算机、手机等)的唯一标识符。而子网掩码则用于划分网络中的子网。 IP地址是一个由32位二进制数组成的地址,通常以点分十进制的形式表示,如192.16…...
【redis 3.2 集群】
目录 一、Redis主从复制 1.概念 2.作用 2.1 数据冗余 2.2 故障恢复 2.3 负载均衡 2.4 高可用 3.缺点 4.流程 4.1 第一步 4.2 第二步 4.3 第三步 4.4 第四步 5.搭建 5.1 主 5.2 从 6.验证 二、Reids哨兵模式 1.概念 2.作用 2.1 监控 2.2 自动故障转移 2.…...
JS 解决鼠标悬浮显示弹窗 迅速离开时弹窗显示到其他位置的延迟问题
解决该问题的思路就是,判断当前鼠标的位置是否在某个div上,如果在这个div上则取消显示悬浮弹窗消息。 首先监听鼠标的移动事件 鼠标移动时判断是否在div里面进行移动了 clientX表示鼠标X的位置 client Y表示鼠标Y的位置 拿到要判断的div元素 获取off…...
树莓派命令行运行调用音频文件的函数,不报错,没有声音解决办法
树莓派接上音频首先需要切换音频不是HDMI,然后可以双击运行wav文件可以播放,但是: 命令行直接运行wav文件报错: Playing WAVE twzc.wav : Signed 16 bit Little Endian, Rate 16000 Hz, Mono命令行运行main方法也是无法播放&am…...
解决无法引入 mysql-connector-j 的问题
开发环境 Windows 10Oracle JDK 1.8Maven 3.8.8IntelliJ IDEA 2022.2.2 问题 在使用 Spring initializr 创建 Spring Boot 项目时,无法引入 mysql-connector-j 这个依赖,报错信息: com.mysql:mysql-connector-j:jar:unknown was not foun…...
解释器模式(Interpreter)
解释器模式是一种行为设计模式,可以解释语言的语法或表达式。给定一个语言,定义它的文法的一种表示,然后定义一个解释器,使用该文法来解释语言中的句子。解释器模式提供了评估语言的语法或表达式的方式。 Interpreter is a behav…...
python读入和读出图像
python提供了PIL库和opencv库对图像进行读取并保存。 图像读入读出 给定一张RGB的彩色图像,PIL库将其读入: import cv2 from PIL import Image # 读入图像 image2 Image.open(cub1.jpg) print(type(image2)) image2_array np.array(image2) print(image2_array…...
每日一题——最长公共前缀
题目 给你一个大小为 n 的字符串数组 strs ,其中包含n个字符串 , 编写一个函数来查找字符串数组中的最长公共前缀,返回这个公共前缀。 数据范围:0≤n≤5000, 0≤len(strsi)≤5000 进阶:空间复杂度 O(1),…...
iOS开发-WebRTC本地直播高分辨率不显示画面问题
iOS开发-WebRTC本地直播高分辨率不显示画面问题 在之前使用WebRTC结合ossrs进行推流时候,ossrs的播放端无法看到高分辨率画面问题。根据这个问题,找到了解决方案。 一、WebRTC是什么 WebRTC是什么呢? WebRTC (Web Real-Time Communicatio…...
python项目virtualenv环境部署正式项目和后台运行实践
pycharm创建virtualenv环境的项目: 在本地虚拟环境项目路径下生成依赖包记录文件,然后上传到linux 服务器项目路径下: 注意注意:要在虚拟环境中生成,才能将所有的项目依赖包构建在 requirements.txt文件中。 pip3 fre…...
平替 Docker - 玩转容器新利器 Podman Desktop (视频)
《OpenShift 4.x HOL教程汇总》 在 podman-desktop 1.2.1 podman 4.4 环境中验证。 文章目录 什么是 podman 和 podman-desktop安装 podman 和 podman-desktop 基本环境Image、Container 和 Pod 的基本操作拉取 Image运行 Container 将 Pod 部署到 Kubernetes安装 Kind 扩展插…...
nodejs+vue+elementui招聘求职网站系统的设计与实现-173lo
(1)管理员的功能是最高的,可以对系统所在功能进行查看,修改和删除,包括企业和用户功能。管理员用例如下: 图3-1管理员用例图 (2)企业关键功能包含个人中心、岗位类型管理、招聘信息…...
静态链接(7/13)
在一个软件项目中,为了完成特定功能,除了自定义函数,还可以使用别人已经封装好的函数库,如 C 函数库。库函数的使用避免了重复“造笼子”的重复工作,提高了代码复用率,大大减轻了软件开发的工作量。 库分为…...
jvs-rules API数据源配置说明(含配置APIdemo视频)
在JVS中,多数据源支持多种形态的数据接入,其中API是企业生产过程中常见的数据形态。使用数据源的集成配置,以统一的方式管理和集成多个API的数据。这些平台通常提供各种数据转换和处理功能,使得从不同数据源获取和处理数据变得更加…...
系统设计 --- MongoDB亿级数据查询优化策略
系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log,共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题,不能使用ELK只能使用…...
跨链模式:多链互操作架构与性能扩展方案
跨链模式:多链互操作架构与性能扩展方案 ——构建下一代区块链互联网的技术基石 一、跨链架构的核心范式演进 1. 分层协议栈:模块化解耦设计 现代跨链系统采用分层协议栈实现灵活扩展(H2Cross架构): 适配层…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...
RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...
学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2
每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...
2023赣州旅游投资集团
单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
