原生表单
HTML部分
raw_form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="" method="post">
<label >用户名</label>
<input type="text" name="username"><br>
<label >密码</label>
<input type="password" name="password" ><br>
<input type="submit" value="注册" />
</form>
</body>
</html>
视图函数部分
hello.py
from flask import Flask, render_template, request
app = Flask(__name__)
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST":
username = request.form.get('username')
password = request.form.get('password')
return render_template("raw_form.html", username=username)
return render_template('raw_form.html')
if __name__ == "__main__":
app.run(debug=True)
flask-wtf
简介|安装包
优点
- 可以抵制CSRF跨站请求伪造的攻击,更具安全性
- 减少重复编写表单HTML
- 提供丰富的表单校验方法
使用
定义表单
# 1、配置密匙
from flask import Flask
app = Flask(__name__)
app.config['SECRET_KEY'] = 'XXXX'
# 2、导包使用
from flask_wtf import FlaskForm #web表单都从该类继承
from wtforms import StringField, SubmitField #字段
from wtforms.validators import DataRequired #字段校验
#定义表单类
class NameForm(FlaskForm):
name = StringField('Name:' validators=[DataRequired()]) #第一个参数将函数构造成label;可以多个校验同时生效,所以为list类型
submit = SubmitField('submit')
视图函数
#...同上
@app.route("/", methods=['GET', 'POST'])
def index():
form = NameForm()
return render_template('index.html', form=form)
获取表单值
# 表单对象获取
name = form.name.data
# request 对象获取
name = request.form.get("name")
form对象渲染表单
<form method='POST'>
{{ form.hidden_tag() }} # 生成一个隐藏字段,供Flask-WTF的CSRF机制使用
{{ form.name.label }} {{ form.name(id='test') }} # 渲染name字段并为其添加属性
{{ form.submit() }}
</form>
flask-bootstrap渲染表单
# 需要在原视图函数中注册Bootstrap ,否则在渲染时候报错找不到bootstrap/wtf.html
form flask_bootstrap import Bootstrap
bootstrap = Bootstrap(app)
单字段渲染
{% import 'bootstrap/wtf.html' as wtf %}
{{ wtf.form_field(form.name, class="form-control text-body") }}
快速渲染
{% import 'bootstrap/wtf.html' as wtf %}
{{ wtf.quick_form(form) }}
WTForms支持的HTML标准字段
| 字段类型 | 说明 | eg | | —- | —- | —- | | StringField | 文本字段 | | | TextAreaField | 多行文本字段 | | | PasswordField | 密码文本字段 | | | HiddenField | 隐藏文本字段 | | | DateField | 文本字段,值为datatime.date格式 | | | DateTimeField | 文本字段,值为datatime.datetime格式 | | | IntegerField | 文本字段,值为整数 | | | DecimalField | 文本字段,值为 decimal.Decimal | | | FloatField | 文本字段,值为浮点数 | | | BooleanField | 复选框,值为 True 和 False | | | RadioField | 一组单选框 | | | SelectField | 下拉列表 | SelectField(label=”请选择环境”, choices=[(1, “无锡”), (7, “HK”), (4, “AWSCA”)], default=1, coerce=int) | | SelectMultipleField | 下拉列表,可选择多个值 | | | FileField | 文件上传字段 | | | SubmitField | 表单提交按钮 | | | FormField | 把表单作为字段嵌入另一个表单 | | | FieldList | 一组指定类型的字段 | |
WTForms支持的验证函数
方法名 | 说明 |
---|---|
DataRequired | 确保转换类型后字段中有数据 |
InputRequired | 确保转换类型前字段中有数据 |
验证电子邮件地址 | |
EqualTo | 比较两个字段的值;常用于要求输入两次密码进行确认的情况 |
IPAddress | 验证 IPv4 网络地址 |
Length | 验证输入字符串的长度 |
MacAddress | 验证Mac地址 |
UUID | 验证UUID |
NumberRange | 验证输入的值在数字范围内 |
Optional | 无输入值时跳过其他验证函数 |
Regexp | 使用正则表达式验证输入值 |
URL | 验证 URL |
AnyOf | 确保输入值在可选值列表中 |
NoneOf | 确保输入值不在可选值列表中 |
拓展
表单中添加图标
.user-icon {
padding-left:30px;
background-repeat: no-repeat;
background-position-x: 4px;
background-position-y: 4px;
background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAWCAYAAAArdgcFAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+5pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ1dWlkOjY1RTYzOTA2ODZDRjExREJBNkUyRDg4N0NFQUNCNDA3IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkIzOUVGMUYxMDY3MTExRTI5OUZEQTZGODg4RDc1ODdCIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkIzOUVGMUYwMDY3MTExRTI5OUZEQTZGODg4RDc1ODdCIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzYgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowMTgwMTE3NDA3MjA2ODExODA4M0ZFMkJBM0M1RUU2NSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowNjgwMTE3NDA3MjA2ODExODA4M0U3NkRBMDNEMDVDMSIvPiA8ZGM6dGl0bGU+IDxyZGY6QWx0PiA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPmdseXBoaWNvbnM8L3JkZjpsaT4gPC9yZGY6QWx0PiA8L2RjOnRpdGxlPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkX/peQAAACrSURBVHja7JSLCYAwDEQbJ3AER+kouoFu0FEcqSM4gk4QE4ggVRPxg1A8OFCSvkqC5xDRaSZ5ciTjyvzuzbMnwKjY34FHAx618yCQXQHAcVFE5+GoVijgyt3UN1/+hPKFd0a9ubxQa6naMjOdOY2jJAdjZIH7tJ8gzRNuZuho5MriUfpLNbhINXk4Cd27pN3AJVqvQlMPSxSz+oegqXuQhz9bNvDpJfY0CzAA6Ncngv5RALIAAAAASUVORK5CYII=);
}
然后在模板里渲染时传入这个类:
<form method="POST">
{{ form.hidden_tag() }}
{{ wtf.form_field(form.username, class="form-control user-icon") }}
{{ wtf.form_field(form.password) }}
{{ wtf.form_field(form.submit) }}
</form>