flask表单
# html 表单
@app.route('/html', methods=['GET', 'POST'])
def html():
form = LoginForm()
if request.method == 'POST':
username = request.form.get('username')
flash('Welcome home, %s!' % username)
return redirect(url_for('index'))
return render_template('pure_html.html')
<!-- -->
{% extends 'base.html' %}
{% block content %}
<h2>Pure HTML Form</h2>
<form method="post">
<label for="username">Username</label><br>
<input type="text" name="username" placeholder="Héctor Rivera"><br>
<label for="password">Password</label><br>
<input type="password" name="password" placeholder="19001130"><br>
<input id="remember" name="remember" type="checkbox" checked>
<label for="remember"><small>Remember me</small></label><br>
<input type="submit" name="submit" value="Log in">
</form>
{% endblock %}
跟普通表单提交并没有什么不同
# flask-wtf 表单渲染
# 字段
from wtforms import StringField, PasswordField, BooleanField, SubmitField
# 验证器,用来校验 字段, 比如 DataRequired 校验数据是否必填。 Length 是长度校验
from wtforms.validators import DataRequired, Length
# 4.2.1 basic form example
class LoginForm(FlaskForm):
username = StringField('Username', validators=[DataRequired()])
password = PasswordField('Password', validators=[DataRequired(), Length(8, 128)])
remember = BooleanField('Remember me')
submit = SubmitField('Log in')
'''
form.username()
输出
u'<input id="username" name="username" type="text" value="">'
form.submit()
输出
u'<input id="submit" name="submit" type="submit" value="Submit">'
一般字段 只有 id 和 name 属性, 如果需要额外属性的话,需要通过下列两种方法
1. 使用 render_kw 属性
username = StringField('Username', render_kw={'placeholder': 'Your Username'})
输出
<input type="text" id="username" name="username" placeholder="Your Username">
2. 在调用字段时传入
form.username(style='width: 200px;', class_='bar')
输出
u'<input class="bar" id="username" name="username" style="width: 200px;" type="text">'
'''
# 渲染表单
from forms import LoginForm
@app.route('/basic')
def basic():
form = LoginForm()
return render_template('basic.html', form=form)
'''
# 模板中使用
<form method="post">
{{ form.csrf_token }} <!-- 渲染CSRF令牌隐藏字段 -->
{{ form.username.label }}<br>{{ form.username }}<br>
{{ form.password.label }}<br>{{ form.password }}<br>
{{ form.remember }}{{ form.remember.label }}<br>
{{ form.submit }}<br>
</form>
'''
<!-- 使用 boostrap -->
<form method="post">
{{ form.csrf_token }}
<div class="form-group">
{{ form.username.label }}
<!-- 在调用字段时传入 class -->
{{ form.username(class='form-control') }}
</div>
<div class="form-group">
{{ form.password.label }}
{{ form.password(class='form-control') }}
</div>
<div class="form-check">
{{ form.remember(class='form-check-input') }}
{{ form.remember.label }}
</div>
{{ form.submit(class='btn btn-primary') }}
</form>
# flask-wtf 处理表单数据
# 提交表单
from flask import request
...
@app.route('/basic', methods=['GET', 'POST'])
def basic():
form = LoginForm() # GET + POST
if request.method == 'POST' and form.validate():
... # 处理POST请求
return render_template('basic.html', form=form) # 处理GET请求
- 这个视图函数需要同时处理 GET 和 POST 两种请求, 当 GET 时, 渲染表单页面, 当 POST 时,校验字段并处理数据
Flask-WTF
提供的 validate_on_submit()
方法合并了这两个操作,因此上面的代码可以简化为:
from flask import Flask, render_template, redirect, url_for, flash
...
@app.route('/basic', methods=['GET', 'POST'])
def basic():
form = LoginForm()
if form.validate_on_submit():
username = form.username.data
flash('Welcome home, %s!' % username)
return redirect(url_for('index'))
return render_template('basic.html', form=form)
form.username.data
返回username
字段的值- 最后将程序重定向到
index
视图。
浏览器中,当单击F5刷新/重载时的默认行为是发送上一个请求。如果上一个请求是POST请求,那么就会弹出一个确认窗口,询问用户是否再次提交表单。
为了避免出现这个容易让人产生困惑的提示,我们尽量不要让提交表单的POST请求作为最后一个请求。
这就是为什么我们在处理表单后返回一个重定向响应,这会让浏览器重新发送一个新的GET请求到重定向的目标URL。 最终,最后一个请求就变成了GET请求。这种用来防止重复提交表单的技术称为PRG(Post/Redirect/Get)模式,即通过对提交表单的POST请求返回重定向响应将最后一个请求转换为GET请求
# 渲染错误消息
<form method="post">
{{ form.csrf_token }}
{{ form.username.label }}<br>
{{ form.username }}<br>
{% for message in form.username.errors %}
<small class="error">{{ message }}</small><br>
{% endfor %}
{{ form.password.label }}<br>
{{ form.password }}<br>
{% for message in form.password.errors %}
<small class="error">{{ message }}</small><br>
{% endfor %}
{{ form.remember }}{{ form.remember.label }}<br>
{{ form.submit }}<br>
</form>