原文:http://www.catonlinepy.tech/
声明:原创不易,未经许可,不得转载
1. 你将学会什么
通过第三天的学习内容,你将对表单的使用有所认识。知道如何通过使用插件来处理应用中的表单,以后在开发过程中也能够更熟练地使用Flask_WTF插件实现表单相关的处理逻辑。今天学习内容涉及到的代码都会托管到github上,在学习本课内容时,一定要自己尝试手敲代码,遇到问题再到猫姐的github上去查看代码,如果实在不知道如何去解决问题,可以在日志下面留言说明具体情况。
2. 表单的插件简介
WTForms作为处理Web表单的插件,是一款支持多个web框架的form组件。Flask-WTF插件对其类WTForms进行封装后以便它能够与Flask完美的结合。在第三天的内容中,我们将引入第一个Flask插件,后续也会对其它的插件进行引入。要知道,插件用得好,可以使web的开发的过程快到飞起。
大家需知道,所有Flask插件都是属于Python的三方包,因此都可以使用pip来进行安装。照旧,我们先进入miao_venv的虚拟环境目录中,将虚拟环境进行激活,然后安装Flask_WTF插件。安装步骤如下:
# 进入到虚拟环境目录,激活虚拟环境
maojie@Thinkpad:~/flask-plan/$ source miao_venv/bin/activate
# 再安装Flask_WTF插件
(miao_venv) maojie@Thinkpad:~/flask-plan$ pip install Flask_WTF
3. 表单插件的使用
今天的代码组织结构如下:
# 使用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
现在猫姐来创建今天的课程目录,步骤如下:
# 在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进行配置,如下所示:
# __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变量,可以向类填充不同的校验函数,它在用户提交表单按钮前验证数据,这里仅仅只验证了字段输入是否为空。
接下来是表单在前端的渲染,将表单内容添加到模板中,让浏览器进行渲染,用户在网页中就可以看到表单了。下面开始进行模板的创建,如下所示:
# 在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. 总结
学习完今天的教程,我们掌握了如下技能:
- 学习了什么是表单插件
- 学习了如何通过表单插件来创建表单对象
- 学习了如何在前端模板中渲染表单对象
- 学习了在视图函数中处理用户通过表单发送的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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。