5、web表单、重定向和用户会话、flask消息


**web表单的视图函数和渲染**

1、安装Flask-WTF
pip install flask-wtf

 附:

Flask-WTF插件介绍

flask-wtf是flask框架的表单验证模块,可以很方便生成表单,也可以当做json数据交互的验证工具,支持热拔插

flask_wtf完全使用wtfforms组件的字段模型,wtforms对字段的定义在fields模块;又分为core和simple,core模块定义了普通使用的字段,simple在core模块的基础上扩展了一些字段,这些字段会自动进行字段级别的效验

常用字段说明:

#core.py

BooleanField:布尔类型,如Flask,True

StringField:字符串类型

DecimalField:小数点文本字段,如‘1.23’

DateField:日期字段,格式‘%Y-%m-%d’

DateTimeField:日期字段,格式 '%Y-%m-%d %H:%M:%S'

FieldList:统一字段类型组成列表   如:FieldList(StringField('Name', [validators.required()]))

FloatField:浮点数类型

IntegerField:整型

SelectMultipleField:多选框

RadioField:单选框

 

#simple.py

TextAreaField:文本域,可接受多行输入

PasswordField:密码字段,输入的不会直接在浏览器明文显示

FileField:上传文件,但不会处理验证文件,需要手动处理

HiddenField:隐藏字段

SubmitField:按钮

TextField:字符串类型的别名,弃用

 

字段的验证序列

字段的参数validators可以指定提交表单的验证序列,按照从左到右的顺序,默认的可选验证在wtforms.validators模块中,已经封装的验证方法有:

DataRequired/data_required:验证数据是否真实存在,即不能为空,必须是非空白字符串,否则触发StopValidation错误。
InputRequired/input_required:和DataRequired的区别在于可以是空白字符串;
Required/required:data_required的别名
Email/email:验证符合邮件的格式,只有最基本的验证;
EqualTo/equal_to:比较两个字段的值,比如密码和确认密码,如果不相等就触发错误,equal_to(field,message),需要输入另一个字段的名字。
IPAddress/ip_address:验证是否是ip地址,默认验证IPV4地址。
MacAddress/mac_address:验证是否符合mac格式;
UUID:是否是uuid格式;
URL/url:验证是否符合url格式;
Regexp/regexp:用提供的正则表达式验证字段;Regexp(r"")
Length/length:设置字段值的长度,Length(min,max);
NumberRange/number_range:设置一个数字字段的取值范围,可以针对浮点数和小数;NumberRange(min,max)
Optional/optional:允许字段为空并停止验证;
NoneOf/none_of:将传入的数据和无效的比较,是抛出异常;Noneof(values).
Anyof/any_of:将传入的数据和预设的数据比较,不是异常。Anyof(values).


示例:
导入相应模块
NameForm表单中有一个名为name的文本字段和一个名为submit的提交按钮
StringField类表示属性为type="text"的< input>函数
SubmitField类表示属性为type="submit"的< input>元素
字段构造函数的第一个参数把表单渲染成HTML时使用的标号
验证函数Required()确保提交的字段不为空

 

 

 

实例:
1、目录结构

 

 

 

2、在hello.py中修改视图函数,使得能够处理表单

from flask import Flask,request,make_response,redirect,render_template
from flask_bootstrap import Bootstrap
from flask_wtf import Form
from wtforms import StringField,SubmitField
from wtforms.validators import Required

app = Flask(__name__)
app.config["SECRET_KEY"] = "123456"
bootstrap = Bootstrap(app)

class NameForm(Form):
    name = StringField('what is your name?', validators=[Required()])
    submit = SubmitField('Submit')

@app.route('/', methods=['GET', 'POST'])
def index():
    name = None
    form = NameForm()
    if form.validate_on_submit():
        name = form.name.data
        form.name.data = ''
    return render_template('index.html', form=form, name=name)

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404

@app.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500


@app.route('/user/<name>')
def user(name):
    return render_template('user.html', name=name)


@app.route('/user/<id>')
def get_user(id):
    user = load_user(id)
    if not user:
        abort(404)
    return '<h1>Hello, %s</h1>' % user.name


if __name__ == '__main__':
    bootstrap.run()

 

3、在templates/index.html中使用Flask-WTF和Flask-Bootstrap渲染表单
模板现在分为两部分,第一部分是页面头部,显示欢迎消息
Jinja2中的条件语句格式为{%if condition%}...{% else %}...{% endif %}
如果条件为True,那么渲染if和else指令之间的值。如果条件的计算结果为False,则渲染else和endif之间的值

{% extends "base.html" %}
{% import "bootstrap/wtf.html" as wtf%}

{% block title %}Flasky{% endblock %}

{% block page_content %}
<div class="page-header">
<h1>Hello, {% if name %}{{ name }}{% else %}Stranger{% endif %}</h1>
</div>
{{ wtf.quick_form(form)}}
{% endblock %}

 

4、base.html

{% extends "bootstrap/base.html" %}

{% block title %}Flasky{% endblock %}

{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="/">Flask</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a href="/">Home</a></li>
</ul>
</div>
</div>
</div>
{% endblock %}

{% block content %}
<div class="container">
<div class="page-header">
{% block page_content %}{% endblock %}
</div>
</div>
{% endblock %}

 

5、结果

 

 


当提交空表单时,Required()验证函数会捕获这个错误

 

 

**重定向和用户会话**

当提交名字后,再重新刷新页面,会出现告警

 

 

处理该告警方式之一是保证最后一次提交是get请求,会出现的问题是,程序处理POST请求时,使用form.name.data获取用户输入的名字,可是一旦这个请求结束了,数据也就丢失了。因此在重定向时,需要保存这个输入的名字,可以使用session

总结:

该能的基本实现流程包括  :通过WTForms插件创建form表单,有一个文本框和提交按钮;通过Flask-Bootstrip插件将form表单渲染为HTML页面;为了访问这个页面,通过定义视图函数建立后台表单处理逻辑,返回HTML页面所需参数

 

 

1、修改hello.py,重定向和用户会话

推荐使用url_for()生成URL,因为这个函数使用URL映射生成URL,从而保证URL和定义的路由兼容,而修改路由的名字后依然可以使用

使用session.get('name')获取字典中键对应的值以避免未找到键的异常情况,对于不存在的键,get()会返回默认值None

from flask import Flask,request,make_response,redirect,render_template,session,url_for

@app.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        session['name'] = form.name.data
        return redirect(url_for('index'))
    return render_template('index.html', form=form, name=session.get('name'))

 

提交名字后再次刷新,没有告警信息

**flash消息**

请求完成,可以通过确认消息,告警或错误提示,告诉用户状态的变化
当用户提交了一项有错误的登录表单后,服务器发回的响应重新渲染了登录表单,并在表单上显示一个消息,提示用户名或密码错误

1、修改hello.py,实现flash

@app.route('/', methods=['GET', 'POST'])
def index():
    form = NameForm()
    if form.validate_on_submit():
        old_name = session.get('name')
        if old_name is not None and old_name != form.name.data:
            flash('Looks like you have changed your name!')
        session['name'] = form.name.data
        return redirect(url_for('index'))
    return render_template('index.html', form = form, name = session.get('name'))

 

2、修改templates/base.html,渲染Flash消息
Flask把get_flashed_messages()函数开放给模板,用来获取并渲染消息

在模板中使用循环是因为在之前的请求循环中每次调用 flash() 函数时都会生成一个消息,
所以可能有多个消息在排队等待显示。 get_flashed_messages() 函数获取的消息在下次调
用时不会再次返回,因此 Flash 消息只显示一次,然后就消失了

{% block content %}
<div class="container">
{% for message in get_flashed_messages() %}
<div class="alert alert-warning">
<button type="button" class="close" data-dismiss="alert">&times;</button>
{{ message }}
</div>
{% endfor %}

{% block page_content %}{% endblock %}
</div>
{% endblock %}

 

3、页面中当两次提交的名字不一样时,会出现告警信息

 

posted @ 2019-10-31 20:19  换头怪  阅读(288)  评论(0编辑  收藏  举报