原生表单

HTML部分

raw_form.html

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Title</title>
  6. </head>
  7. <body>
  8. <form action="" method="post">
  9. <label >用户名</label>
  10. <input type="text" name="username"><br>
  11. <label >密码</label>
  12. <input type="password" name="password" ><br>
  13. <input type="submit" value="注册" />
  14. </form>
  15. </body>
  16. </html>

视图函数部分

hello.py

  1. from flask import Flask, render_template, request
  2. app = Flask(__name__)
  3. @app.route("/", methods=["GET", "POST"])
  4. def index():
  5. if request.method == "POST":
  6. username = request.form.get('username')
  7. password = request.form.get('password')
  8. return render_template("raw_form.html", username=username)
  9. return render_template('raw_form.html')
  10. if __name__ == "__main__":
  11. app.run(debug=True)

flask-wtf

简介|安装包

优点

  • 可以抵制CSRF跨站请求伪造的攻击,更具安全性
  • 减少重复编写表单HTML
  • 提供丰富的表单校验方法

安装:pip install flask-WTF

使用

定义表单

  1. # 1、配置密匙
  2. from flask import Flask
  3. app = Flask(__name__)
  4. app.config['SECRET_KEY'] = 'XXXX'
  5. # 2、导包使用
  6. from flask_wtf import FlaskForm #web表单都从该类继承
  7. from wtforms import StringField, SubmitField #字段
  8. from wtforms.validators import DataRequired #字段校验
  9. #定义表单类
  10. class NameForm(FlaskForm):
  11. name = StringField('Name:' validators=[DataRequired()]) #第一个参数将函数构造成label;可以多个校验同时生效,所以为list类型
  12. submit = SubmitField('submit')

视图函数

  1. #...同上
  2. @app.route("/", methods=['GET', 'POST'])
  3. def index():
  4. form = NameForm()
  5. return render_template('index.html', form=form)

获取表单值

  1. # 表单对象获取
  2. name = form.name.data
  3. # request 对象获取
  4. name = request.form.get("name")

form对象渲染表单

  1. <form method='POST'>
  2. {{ form.hidden_tag() }} # 生成一个隐藏字段,供Flask-WTF的CSRF机制使用
  3. {{ form.name.label }} {{ form.name(id='test') }} # 渲染name字段并为其添加属性
  4. {{ form.submit() }}
  5. </form>

image.png

flask-bootstrap渲染表单

  1. # 需要在原视图函数中注册Bootstrap ,否则在渲染时候报错找不到bootstrap/wtf.html
  2. form flask_bootstrap import Bootstrap
  3. bootstrap = Bootstrap(app)
  • 单字段渲染

    1. {% import 'bootstrap/wtf.html' as wtf %}
    2. {{ wtf.form_field(form.name, class="form-control text-body") }}
  • 快速渲染

    1. {% import 'bootstrap/wtf.html' as wtf %}
    2. {{ 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 确保转换类型前字段中有数据
Email 验证电子邮件地址
EqualTo 比较两个字段的值;常用于要求输入两次密码进行确认的情况
IPAddress 验证 IPv4 网络地址
Length 验证输入字符串的长度
MacAddress 验证Mac地址
UUID 验证UUID
NumberRange 验证输入的值在数字范围内
Optional 无输入值时跳过其他验证函数
Regexp 使用正则表达式验证输入值
URL 验证 URL
AnyOf 确保输入值在可选值列表中
NoneOf 确保输入值不在可选值列表中

拓展

表单中添加图标

  1. .user-icon {
  2. padding-left:30px;
  3. background-repeat: no-repeat;
  4. background-position-x: 4px;
  5. background-position-y: 4px;
  6. background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABcAAAAWCAYAAAArdgcFAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA+5pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIHhtbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyIgeG1wTU06T3JpZ2luYWxEb2N1bWVudElEPSJ1dWlkOjY1RTYzOTA2ODZDRjExREJBNkUyRDg4N0NFQUNCNDA3IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOkIzOUVGMUYxMDY3MTExRTI5OUZEQTZGODg4RDc1ODdCIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOkIzOUVGMUYwMDY3MTExRTI5OUZEQTZGODg4RDc1ODdCIiB4bXA6Q3JlYXRvclRvb2w9IkFkb2JlIFBob3Rvc2hvcCBDUzYgKE1hY2ludG9zaCkiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDowMTgwMTE3NDA3MjA2ODExODA4M0ZFMkJBM0M1RUU2NSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDowNjgwMTE3NDA3MjA2ODExODA4M0U3NkRBMDNEMDVDMSIvPiA8ZGM6dGl0bGU+IDxyZGY6QWx0PiA8cmRmOmxpIHhtbDpsYW5nPSJ4LWRlZmF1bHQiPmdseXBoaWNvbnM8L3JkZjpsaT4gPC9yZGY6QWx0PiA8L2RjOnRpdGxlPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PkX/peQAAACrSURBVHja7JSLCYAwDEQbJ3AER+kouoFu0FEcqSM4gk4QE4ggVRPxg1A8OFCSvkqC5xDRaSZ5ciTjyvzuzbMnwKjY34FHAx618yCQXQHAcVFE5+GoVijgyt3UN1/+hPKFd0a9ubxQa6naMjOdOY2jJAdjZIH7tJ8gzRNuZuho5MriUfpLNbhINXk4Cd27pN3AJVqvQlMPSxSz+oegqXuQhz9bNvDpJfY0CzAA6Ncngv5RALIAAAAASUVORK5CYII=);
  7. }

然后在模板里渲染时传入这个类:

  1. <form method="POST">
  2. {{ form.hidden_tag() }}
  3. {{ wtf.form_field(form.username, class="form-control user-icon") }}
  4. {{ wtf.form_field(form.password) }}
  5. {{ wtf.form_field(form.submit) }}
  6. </form>

密码输入框值可见、隐藏切换功能

提交表单,body中密码为明文问题处理