Flask Web表单验证

Flask Web表单验证

一、开发准备:

1、安装Flask-WTF扩展:

pip install flask-wtf

2、需要导入的模块:

  • 导入Form的基类:
  • from flask.ext.wtf improt Form

  • 导入表单的文本域和提交域:
  • from wtforms improt StringField,SubmitField

  • 导入表单非空的验证函数 Required() :
  • from wrforms.validators import Required

    3、设置跨站请求伪造保护:

    为了实现CSRF保护,Flask-WTF需要程序设置一个密钥。Flask-WTF使用这个密钥生成加密令牌,再用令牌验证请求中表单数据的真伪

    app.config['SECRET_KEY']='hard to guess string'

    二、简单的POST提交方式:

    1、定义表单的类:

    使用Flask-WTF 时,每个Web 表单都由一个继承自Form 的类表示。这个类定义表单中的
    一组字段,每个字段都用对象表示

    class NameForm(Form):
        #定义name的文本表单的构造函数:
        name = StringField('What\'s your name?',validators=[Required()])
        #定义submit的提交表单按钮:
        submit = SubmitField('Submit')
    

    StringField构造函数中的可选参数validators用来在接受用户提交的数据之前验证数据,验证函数Required()确保提交的字段不为空

    2、在视图函数中处理表单:

    @app.route('/', methods=['GET', 'POST'])
    def index():
        name = None
        #实例化一个NameForm()对象
        form = NameForm()
        if form.validate_on_submit():
            #获得name表单的数据
            name = form.name.data
            #提交完数据后,清空表单的数据:
            form.name.data = ''
        return render_template('index.html', form=form, name=name)
    
  • 注册处理程序的请求方式:
  • @app.route('/',method=['GET','POST']),如果没有指定请求方式,默认为GET提交方式

  • 判断表单的文本字段是否为空:
  • if form.validate_on_submit():
    

    当文本字段为空时,验证函数返回False,否则返回True

  • 提交过程:
  • 第一次(GET):由于name = None,验证函数返回False,不执行if语句的内容,在渲染的网页上显示一个空表单

    第二次(POST):由于用户提交了name字段的表单数据,验证函数返回True,执行if语句后得到name字段的表单数据,再清空表单,最后传给渲染的模板

    3、在模板中渲染:

    <form method="POST">
        {% import "bootstrap/wtf.html" as wtf %}
            <div class="page-header">
                <h1>Hello
                    {% if name %}
                        {{ name }}!<br>Welcome to my website!
                    {% else %}
                        Stranger
                    {% endif %}
        {{ wtf.quick_form(form) }}
    

    jinja2循环渲染

  • 当第一次接受到name数据为None时,网页渲染Hello!Stranger

  • 当第二次接受到的name数据为name.data时,网页渲染Hello!{{ name }}

  • 使用BootStrap样式渲染表单:

  • 调用预先定义的表单样式:
  • { % import "bootstrap/wtf.html" as wtf % }

  • 渲染传入的表单:
  • {{ wtf.quick_form(form) }}

    三、设置重定向和用户会话和Flash消息:

    使用简单POST提交方式,当刷新页面之后会再次提交表单

    一般情况下,最好别让Web程序把POST提交方式作为浏览器发送的最后一个请求

    1、POST/重定向/GET模式:

    from flask import Flask, render_template, session, redirect, 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'))
    
  • 设置session
  • 由于使用这种模式,当这个请求结束之后,数据也就丢失了,但是程序可以把数据储存在session(用户会话)中,在请求之前“记住”数据

    session['name'] = form.name.data
    
  • 重定向响应:
  • return redirect(url_for('index'))
    

    redirect()是个辅助函数,用来生成HTTP重定向响应,使用Flask提供的URL生成函数url_for(),一般情况下,选择视图函数的名字作为路由端点

  • 通过session获得name参数的值:
  • name = session.get('name')
    

    2、Flash消息:

  • 视图函数的操作:
  • from flask import Flask, render_template, session, redirect, url_for, 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'))
    

    在这个版本中,每一次提交数据都会和储存在session中的数据比较,如果两个数据不相同,就会调用flash()函数

  • 模板渲染:
  • {% for message in get_flashed_messages() %}
        <div class="alert alert-warning">
            <button type="button" class="close" data-dismiss="alert">&times;</button>
            {{ message }}
    {% endfor %}
    

    四、操作数据库验证表单:

    1、视图函数操作:

    @app.route('/', methods=['GET', 'POST'])
    def index():
        form = NameForm()
        if form.validate_on_submit():
            user = User.query.filter_by(username=form.name.data).first()
            if user is None:
                user = User(username = form.name.data)
                db.session.add(user)
                session['known'] = False
            else:
                session['known'] = True
            session['name'] = form.name.data
            form.name.data = ''
            return redirect(url_for('index'))
        return render_template('index.html',form = form, name = session.get('name'),known = session.get('known', False))
    
  • 在这个版本中,提交表单后,程序会通过filter()过滤器在数据库查找form.name.data与之相同的数据
  • 2、渲染模板:

    <div class="page-header">
        <h1>Hello, 
        {% if name %}
            {{ name }}
        {% else %}
            Stranger{% endif %}!
        {% if not known %}
            <p>Pleased to meet you!</p>
        {% else %}