第3天:在Flask应用中使用表单—Flask-WTF

原文:http://www.catonlinepy.tech/
声明:原创不易,未经许可,不得转载css

1. 你将学会什么

经过第三天的学习内容,你将对表单的使用有所认识。知道如何经过使用插件来处理应用中的表单,之后在开发过程当中也可以更熟练地使用Flask_WTF插件实现表单相关的处理逻辑。今天学习内容涉及到的代码都会托管到github上,在学习本课内容时,必定要本身尝试手敲代码,遇到问题再到猫姐的github上去查看代码,若是实在不知道如何去解决问题,能够在日志下面留言说明具体状况。html

2. 表单的插件简介

WTForms做为处理Web表单的插件,是一款支持多个web框架的form组件。Flask-WTF插件对其类WTForms进行封装后以便它可以与Flask完美的结合。在第三天的内容中,咱们将引入第一个Flask插件,后续也会对其它的插件进行引入。要知道,插件用得好,可使web的开发的过程快到飞起。前端

你们需知道,全部Flask插件都是属于Python的三方包,所以均可以使用pip来进行安装。照旧,咱们先进入miao_venv的虚拟环境目录中,将虚拟环境进行激活,而后安装Flask_WTF插件。安装步骤以下:python

# 进入到虚拟环境目录,激活虚拟环境
maojie@Thinkpad:~/flask-plan/$ source miao_venv/bin/activate

# 再安装Flask_WTF插件
(miao_venv) maojie@Thinkpad:~/flask-plan$ pip install Flask_WTF

3. 表单插件的使用

今天的代码组织结构以下:git

# 使用tree命令查看
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3$ tree
.
├── form_demo
│   ├── __init__.py
│   ├── routes.py
│   └── templates
│       ├── form.html
│       └── layout.html
└── run.py

如今猫姐来建立今天的课程目录,步骤以下:github

# 在flask-course-primary目录下建立第三天的课程day3目录
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary$ mkdir day3

# 进入day3目录
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary$ cd day3

# 新建form_demo
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3$ mkdir form_demo

# 进入到form_demo包
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3$ cd form_demo/

# 在form_demo包中新建__init__.py文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/form_demo$ touch __init__.py

# 在form_demo新建routes.py路由文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/form_demo$ touch routes.py

# 在day3目录下新建run.py文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/$ touch run.py

上面将课程目录建立好后,如今咱们开始表单的建立。在建立表单以前,猫姐先在__init__.py文件中对Flask_WTF进行配置,以下所示:web

# __init__.py文件中的内容
from flask import Flask    # 从flask包中导入Flask类

app = Flask(__name__)      # 经过Flask类建立一个app实例

app.config['SECRET_KEY'] = 'miaojie is great!'  # 对Flask_WTF进行配置

from form_demo import routes

# 解释:对Flask_WTF进行配置主要是为了防跨站请求伪造保护。由于在默认的状况下,Flask_WTF可以保护全部的表单免受跨站请求伪造的攻击(Cross-Site Request Forgery,CSRF),可是在特殊状况下,一些恶意网站会把请求发送到被攻击者已登陆的其它网站时就会发生CSRF攻击。为了实现CSRF的保护,Flask_WTF须要程序设置一个密钥,而后它使用密钥去生成一个加密令牌,再用令牌验证请求中的表单数据的真伪。(这里不懂也没事,问题不大!)

下面开始一个简单的Web 表单,猫姐开始利用Flask_WTF插件来建立Web表单,表单内容写入到routes.py文件中,以下所示:数据库

# routes.py文件中的内容
# 从flask_wtf库中导入FlaskForm类
from flask_wtf import FlaskForm

# 从wtforms中导入表单的字段对象类      
from wtforms import StringField, PasswordField, BooleanField, SubmitField 

# 从wtforms.validators字段验证器中导入DataRequired验证函数 
from wtforms.validators import DataRequired    

# LoginForm类函数,继承自FlaskForm基类
class LoginForm(FlaskForm):
     # 表单包括用户名,密码和是否记住密码及一个提交按钮
     username = StringField('Username', validators=[DataRequired()])
     password = PasswordField('Password', validators=[DataRequired()])
     remember = BooleanField('Remember Me')
     submit = SubmitField('Sign In')

因为只须要用户输入用户名、密码、记住登陆状态以及提交按钮,因此表示web表单的LoginForm仅包含了用户名,密码和是否记住密码可选框以及提交按钮这4个字段。其中,StringField类表示属性为type="text"的<input>元素;PasswordField类表示属性为type="password"的<input>元素;BooleanField表示为true或false的可选框;SubmiteField表示属性为type="submit"的<input>元素,而Username,Password,Remember Me表示标签名称(label)。在字段类中的可选参数—validators—是一个list变量,能够向类填充不一样的校验函数,它在用户提交表单按钮前验证数据,这里仅仅只验证了字段输入是否为空。flask

接下来是表单在前端的渲染,将表单内容添加到模板中,让浏览器进行渲染,用户在网页中就能够看到表单了。下面开始进行模板的建立,以下所示:浏览器

# 在form_demo中建立templates目录
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/form_demo$ mkdir templates

# 进入templates目录
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/form_demo/$ cd templates

# 建立基模板layout.html
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/form_demo/templates$ touch layout.html

# 建立子模板form.html
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day3/form_demo/templates$ touch form.html

在第二课中猫姐已经讲到了模板的继承,在今天的课程中仍是用到继承这个概念。在templates/layout.html中写入以下代码:

<!-- layou.html文件中的内容 -->
<html>
    <head>
      {% if title %}
        <title>{{ title }} - 表单的使用-喵星在线</title>
      {% else %}
        <title>表单的使用-喵星在线</title>
      {% endif %}
    </head>
    <body>
       {% block content %}
       {% endblock %}
    </body>
</html>

而后子模板继承基模板,在templates/form.html中写入以下代码:

<!-- form.html文件中的内容 -->
{% extends "layout.html" %}

{% block content %}
    <h1>Sign In</h1>
    <form action="" method="post">
            # 防跨站伪造请求  
            {{html_form.hidden_tag() }}
        <div>
            # 显示Username标签名称 
            {{ html_form.username.label }}
            # Username输入框 
            {{ html_form.username() }}
        </div>
         <div>
            # 显示Password标签名称
            {{ html_form.password.label }}
            # 密码输入框
            {{ html_form.password() }}
        </div>
        <div>
            # 显示Remember Me标称名称
            {{ html_form.remember.label }}
            # 是否勾选记住密码框
            {{ html_form.remember() }}
        </div>
        <div>
            # 显示提交按钮
            {{ html_form.submit() }}
        </div>
    </form>
{% endblock content %}

经过<form></form>建立表单,它的action属性告诉浏览器用户在提交表单时将发送请求的URL,当action为空时,表示请求的是当前的URL页面,里面也能够输入用户想请求的URL。method属性指定了表单提交给服务器的HTTP请求方法,由于里面要传送数据,因此请求方法为post。

上面已经完成了前台的form表的显示(渲染)工做,这时就须要在视图函数中将表明表单的类传递到前端模板文件中,这里是form.html文件。下面在routes.py中编写视图函数:

# routes.py文件中的内容
# 从flask库中导入render_template
from flask import render_template
# 表单内容
# 从flask_wtf库中导入FlaskForm类
from flask_wtf import FlaskForm

# 从wtforms中导入表单的字段对象类      
from wtforms import StringField, PasswordField, BooleanField, SubmitField 

# 从wtforms.validators字段验证器中导入DataRequired验证函数 
from wtforms.validators import DataRequired    

# 编写LoginForm类函数,继承FlaskForm基类
class LoginForm(FlaskForm):
     # 表单包括用户名,密码和是否记住密码及一个提交按钮
     username = StringField('Username', validators=[DataRequired()])
     password = PasswordField('Password', validators=[DataRequired()])
     remember = BooleanField('Remember Me')
     submit = SubmitField('Sign In')

# 添加视图函数渲染表单内容
@app.route('/login')
def login():
     # 对类LoginForm的实例
     form = LoginForm()
     # 将视图函数中的变量form传到模板form.html文件中去
     return render_template('form.html', title='第三天', html_form=form)

如今,全部代码已编写完成,经过pythonn run.py(run.py文件的内容与次日教程的内容相同))将web程序拉起,开始验证结果,在浏览器中输入http://127.0.0.1:5000/login,效果图以下所示:
图片描述

在上面的结果中,猫姐只是完成了表单前台的渲染,可是还不能在表单中发送数据,下面猫姐将介绍,后台接收到用户发送form表单内容后,如何进行处理。

上面的例子中,在表单中输入用户名和密码后,点击提交按钮,发现浏览器没有任何反应,后台程序并不能处理post请求,因此如今须要修改后台程序routes.py,让其可以处理post请求,更改代码以下:

# routes.py文件中对视图函数进行修改,处理post语法

# 添加视图函数渲染表单内容
# 在装饰器函数中添加http请求方法
@app.route('/login',methods=['GET','POST'])
def login():
     # LoginForm的实例化
     form = LoginForm()
     # 添加处理post请求的代码
     if from.validate_on_subimit():
          # 调用flash函数,在flash消息中提示用户及记住remember状态成功
          flash('登陆用户 {},记住remember状态{}成功'.format(form.username.data,form.remember.data), 'success')

     # 将视图函数中的变量form传到模板form.html文件中去
     return render_template('form.html', title='第三天', html_form=form)

# 解释:flash消息中,form.username.data是获取表单中的用户名,form.remember.data是获取表单中的记住密码的状态(它的状态是true或是false)

当在浏览器中点击提交按钮后,浏览器会发送post请求,就会执行上面的if条件语句,并渲染flash消息到浏览器中。浏览器默认发送的是get请求,因此当没有点击提交按钮时,就会跳过if语句,直接执行return语句。

可是当你调用flash函数后,在浏览器中并无渲染flash消息,这是由于须要将消息渲染到基模板中,才能在全部的子模板中显示出来。如今来更新layout.html代码:

<!-- layout.html文件中的内容 -->
<html>
    <head>
      {% if title %}
        <title>{{ title }} - 表单的使用-喵星在线</title>
      {% else %}
        <title>表单的使用-喵星在线</title>
      {% endif %}
    </head>
    <body>
        <!-- 渲染flash消息 -->
        {% with messages = get_flashed_messages(with_categories=true) %}
            {% if messages %}
                {% for category, message in messages %}
                    <div class="alert alert-{{ category }}">
                        {{ message }}
                    </div>
                {% endfor %}
            {% endif %}
        {% endwith %}
       {% block content %}
       {% endblock %}
    </body>
</html>

在浏览器中打开网址 http://localhost:5000/,查看结果:
图片描述

在上图中就能够将flash的消息渲染出来了,可是,这个flash消息并不会消失,而且显示效果也不美观。这是由于咱们没有给它添加任何css样式,这个问题在后面的教程中也会讲到。

4. 总结

学习完今天的教程,咱们掌握了以下技能:

  1. 学习了什么是表单插件
  2. 学习了如何经过表单插件来建立表单对象
  3. 学习了如何在前端模板中渲染表单对象
  4. 学习了在视图函数中处理用户经过表单发送的post请求

第四天的内容,咱们将会带领你们一块儿了解使用flask的插件来建立数据库,怎么对数据库进行操做,第三天的内容就到这里,喜欢的同窗们能够在下面点赞留言,或是访问个人博客地址:http://www.catonlinepy.tech/ 加入咱们的QQ群进一步交流学习!

5. 代码的获取

今天的课程就到这里,你们能够到github上去获取以上教程中的全部代码:https://github.com/miaojie19/...

具体下载代码的命令以下:

# 使用git命令下载flask-course-primary仓库全部的代码
git clone https://github.com/miaojie19/flask-course-primary.git

# 下载完成后,进入day3目录下面,便可看到今天的代码
cd flask-course-primary
cd day3

图片描述

相关文章
相关标签/搜索