02 模板
模板
- flask-script
- jinja2简单使用
- 过滤器
- 控制代码块
- 宏、继承、包含
- Flask特殊变量和方法
- web表单
Flask-Script
通过使用Flask-Script扩展,我们可以在Flask服务器启动的时候,通过命令行的方式传入参数。而不仅仅通过app.run()方法中传参,比如我们可以通过:
python hello.py runserver [-host ip地址]
以上代码告诉服务器在哪个网络接口监听来自客户端的连接。默认情况下,服务器只监听来自服务器所在的计算机发起的连接,即localhost连接。
我们可以通过python hello.py runserver --help来查看参数

通过命令行,启动项目
创建一个名为 test1.py 的项目
# coding:utf8 from flask import Flask from flask_script import Manager app = Flask(__name__) # 初始化一个Maneger实例,和当前的应用关联起来 manager = Manager(app) @app.route('/') def index(): return 'hello word' if __name__ == '__main__': manager.run()
运行项目
python test1.py runserver
Jinja2模板引擎
模板
在前面的示例中,视图函数的主要作用是生成请求的响应,这是最简单的请求。实际上,视图函数有两个作用:处理业务逻辑和返回响应内容。在大型应用中,把业务逻辑和表现内容放在一起,会增加代码的复杂度和维护成本。本节学到的模板,它的作用即是承担视图函数的另一个作用,即返回响应内容。
- 模板其实是一个包含响应文本的文件,其中用占位符(变量)表示动态部分,告诉模板引擎其具体的值需要从使用的数据中获取
- 使用真实值替换变量,再返回最终得到的字符串,这个过程称为“渲染”
- Flask是使用 Jinja2 这个模板引擎来渲染模板
使用模板的好处:
- 视图函数只负责业务逻辑和数据处理(业务逻辑方面)
- 而模板则取到视图函数的数据结果进行展示(视图展示方面)
- 代码结构清晰,耦合度低
Jinja2
两个概念:
- Jinja2:是 Python 下一个被广泛应用的模板引擎,是由Python实现的模板语言,他的设计思想来源于 Django 的模板引擎,并扩展了其语法和一系列强大的功能,其是Flask内置的模板语言。
- 模板语言:是一种被设计来自动生成文档的简单文本格式,在模板语言中,一般都会把一些变量传给模板,替换模板的特定位置上预先定义好的占位变量名。
渲染模版函数
- Flask提供的 render_template 函数封装了该模板引擎
- render_template 函数的第一个参数是模板的文件名,后面的参数都是键值对,表示模板中变量对应的真实值。
使用
{{}} 来表示变量名,这种 {{}} 语法叫做变量代码块
<h1>{{ post.title }}</h1>
Jinja2 模版中的变量代码块可以是任意Python类型或者对象,只要它能够被Python的str()方法转换为一个字符串就可以,比如,可以通过下面的方式显示一个字典或者列表中的某个元素
{{your_dict['key']}}
{{your_list[0]}}
用 {%%} 定义的控制代码块,可以实现一些语言层次的功能,比如循环或者if语句
{% if user %}
{{ user }}
{% else %}
hello!
<ul>
{% for index in indexs %}
<li> {{ index }} </li>
{% endfor %}
</ul>
注释
- 使用 {# #} 进行注释,注释的内容不会在html中被渲染出来
{# {{ name }} #}
把templates目录设置为Templates目录(没什么用处,就是文件夹变了颜色,可以不设置)
把pycharm的模板语言设置为 Flask的内置的模板语言Jinja2

Flask和jango模板变量的显著区别是,只需变量能解析成字符串就可以在模板中使用,不像jango必须是json的格式
创建一个test2.pyde项目
# coding:utf8 from flask import Flask from flask_script import Manager from flask import render_template app = Flask(__name__) manager = Manager(app) class User(object): def __init__(self, name, age=18): self.name = name self.age = age @app.route('/index') def demo1(): # 这个和jango的区别是,只需要通过变量能解析成字符串就行 name = u'你好' li = [0] dirc = {"name": "zhangbiao"} user = User("zyc") return render_template('temp01.html', name=name, li=li, dirc=dirc, user=user) if __name__ == '__main__': manager.run()
前端的页面(temp01.html)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1> {{ name }}</h1> <h1>{{ dirc.name}}</h1> <h1>{{ li[0] }}</h1> <h1>{{ user.name }} </body> </html>
运行test2.py的项目
python test2.py runserver
在浏览器中输入
http://127.0.0.1:5000/index

过滤器
过滤器的本质就是函数。有时候我们不仅仅只是需要输出变量的值,我们还需要修改变量的显示,甚至格式化、运算等等,而在模板中是不能直接调用 Python 中的某些方法,那么这就用到了过滤器。
使用方式:
过滤器的使用方式为:变量名 | 过滤器。
{{variable | filter_name(*args)}}
如果没有任何参数传给过滤器,则可以把括号省略掉
{{variable | filter_name}}
如:
{{variable | capitalize}}
这个过滤器的作用:把变量variable 的值的首字母转换为大写,其他字母转换为小写
常见内建过滤器
safe:禁用转义
<p>{{ '<em>hello</em>' | safe }}</p>
capitalize:把变量值的首字母转成大写,其余字母转小写
<p>{{ 'hello' | capitalize }}</p>
upper:把值转成大写
<p>{{ 'hello' | upper }}</p>
title:把值中的每个单词的首字母都转成大写
<p>{{ 'hello' | title }}</p>
reverse:字符串反转
<p>{{ 'olleh' | reverse }}</p>
format:格式化输出
<p>{{ '%s is %d' | format('name',17) }}</p>
striptags:渲染之前把值中所有的HTML标签都删掉
<p>{{ '<em>hello</em>' | striptags }}</p>
truncate: 字符串截断(只取里面的多少个字符)
<p>{{ 'hello every one' | truncate(9)}}</p>
列表操作
first:取第一个元素
<p>{{ [1,2,3,4,5,6] | first }}</p>
last:取最后一个元素
<p>{{ [1,2,3,4,5,6] | last }}</p>
length:获取列表长度
<p>{{ [1,2,3,4,5,6] | length }}</p>
sum:列表求和
<p>{{ [1,2,3,4,5,6] | sum }}</p>
sort:列表排序
<p>{{ [6,2,3,1,5,4] | sort }}</p>
语句块过滤
{% filter upper %}
一大堆文字
{% endfilter %}
创建一个test3.py的项目
# coding:utf8 from flask import Flask,render_template import sys reload(sys) sys.setdefaultencoding('utf-8') app = Flask(__name__) class User(object): def __init__(self, name, age=18): self.name = name self.age = age @app.route('/') def demo(): user1 = User(name='a', age=18) user2 = User(name='b', age=18) user3 = User(name='c', age=18) user4 = User(name='d', age=18) user5 = User(name='e', age=18) # 数组主要用于在模板中求出,所有的和 array = [user1, user2, user3, user4, user5] name = "<script>for(var i = 0; i < 1; i++){ alert('哈哈') }</script>" return render_template('temp02.html', name=name, array=array) if __name__ == '__main__': app.run(debug=True)
在模板中创建temp02.html的文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p>{{ "asjdfkqwrjq" | capitalize }}</p> <p>{{ "asjdfkqwrjq" | upper }}</p> <p>{{ "FJJAKS" | lower }}</p> <p>{{ "asjdfkqwrjq" | length }}</p> <p>{{ "hello world" | title }}</p> <p>{{ "HELLO WORLD" | lower | title }}</p> <p>{{ "HELLO WORLD" | reverse }}</p> <p>{{ "<h1>ASFSF</h1>" | safe }}</p> <p>{{ "<h1>哈哈哈哈</h1>" | striptags }}</p> {#<p>{{ name | escape }}</p>#} [4, 7, 1, 3, 9] <p>{{ [4, 7, 1, 3, 9] | first }}</p> <p>{{ [4, 7, 1, 3, 9] | last }}</p> <p>{{ [4, 7, 1, 3, 9] | sum }}</p> <p>{{ [4, 7, 1, 3, 9] | sort | first }}</p> <p>age sum = {{ array | sum(attribute='age') }}</p> {% filter upper %} ajksdfjlkasdjfl {% endfilter %} </body> </html>
对模板中的局部代码进行解释
sum(attribute='age') 过滤器对数组中的具体的属性进行求和
<p>age sum = {{ array | sum(attribute='age') }}</p>
运行项目
自定义过滤器
过滤器的本质是函数。当模板内置的过滤器不能满足需求,可以自定义过滤器。自定义过滤器有两种实现方式:
- 一种是通过Flask应用对象的 add_template_filter 方法
- 通过装饰器来实现自定义过滤器
方式一
通过调用应用程序实例的add_template_filter方法实现自定义过滤器。该方法第一个参数是函数名,第二个参数是自定义的过滤器名称:
add_template_filter(自定义的函数,“自定义过滤器的名字”)
创建一个test4.py的项目
# coding:utf8 from flask import Flask,render_template app = Flask(__name__) # 自定义一个多路器让数组反序 def do_reverse(array): array.reverse() return array @app.route('/') def demo(): return render_template('temp03.html') # 第一个参数接受的是函数的名字,第二个是自定义过滤器的名字 app.add_template_filter(do_reverse, 'arrayreverse') if __name__ == '__main__': app.run(debug=True)
在模板中创建temp03.html模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <p>[4, 7, 1, 3, 9]</p> <p>{{ [4, 7, 1, 3, 9] | arrayreverse }}</p> </body> </html>
运行项目:

方式二
用装饰器来实现自定义过滤器。装饰器传入的参数是自定义的过滤器名称。
格式:
@app.template_filter('过滤器的名字') def fun(): '''自定义过滤器的函数''' pass
创建一个test5.py的项目
# coding:utf8 from flask import Flask,render_template app = Flask(__name__) # 自定义一个多路器让数组反序 @app.template_filter("arrayreverse") def do_reverse(array): array.reverse() return array @app.route('/') def demo(): return render_template('temp03.html') if __name__ == '__main__': app.run(debug=True)
模板还是用上面的temp03.html
运行项目

模版注释
模板中的注释使用{# 注释内容 #}来定义,不会出现在生成的HTML中,例如:
{# 我是注释 #}
控制代码块
if语句
Jinja2 语法中的if语句跟 Python 中的 if 语句相似,后面的布尔值或返回布尔值的表达式将决定代码中的哪个流程会被执行:
{%if user.is_logged_in() %}
<a href='/logout'>Logout</a>
{% else %}
<a href='/login'>Login</a>
{% endif %}
过滤器可以被用在 if 语句中
{% if comments | length > 0 %}
There are {{ comments | length }} comments
{% else %}
There are no comments
{% endif %}
循环
- 我们可以在 Jinja2 中使用循环来迭代任何列表或者生成器函数
{% for post in posts %}
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.text | safe }}</p>
</div>
{% endfor %}
- 循环和if语句可以组合使用,以模拟 Python 循环中的 continue 功能,下面这个循环将只会渲染post.text不为None的那些post:
{% for post in posts if post.text %}
<div>
<h1>{{ post.title }}</h1>
<p>{{ post.text | safe }}</p>
</div>
{% endfor %}
在一个 for 循环块中你可以访问这些特殊的变量:

创建一个test.06的项目
from flask import Flask,render_template app = Flask(__name__) class User(object): def __init__(self, name, age=18): self.name = name self.age = age @app.route('/') def demo3(): user = User(name='a') user1 = User(name='a', age=18) user2 = User(name='b', age=28) user3 = User(name='c', age=16) user4 = User(name='d', age=13) user5 = User(name='e', age=38) array = [user1, user2, user3, user4, user5] array_num = [4, 3, 2, 7] return render_template('temp04.html', user=user, array=array, array_num=array_num) if __name__ == '__main__': app.run(debug=True)
创建一个temp06的模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% if user.age > 18 %} <a href="/happy">去happy</a> {% else %} 18禁 {% endif %}<br/> {% for user in array %} {{ user.name }},{{ user.age }}<br> {% endfor %} <hr/> {% for user in array %} {% if user.age > 18 %} index:{{ loop.index0 }},{{ user.name }},{{ user.age }}<br> {% endif %} {% endfor %} <hr/> {% for user in array if user.age > 18 %} index:{{ loop.index0 }},{{ user.name }},{{ user.age }}<br> {% endfor %} <hr/> <p>遍历的时候有空格</p> {% for num in array_num %} {{ num }} {% endfor %} <p>遍历时去掉空格,只需要加上减号即可</p> {% for num in array_num -%} {{ num }} {%- endfor %} </body> </html>
运行项目

宏
对宏(macro)的理解:
- 把它看作 Jinja2 中的一个函数,它会返回一个模板或者HTML字符串
- 为了避免反复地编写同样的模板代码,出现代码冗余,可以把他们写成函数以进行重用
- 需要在多处重复使用的模板代码片段可以写入单独的文件,再包含在所有模板中,以避免重复
使用方式一
- 定义宏
{% macro 宏的名字(name,value='',type='text') %} <宏的名字type="{{type}}" name="{{name}}" value="{{value}}" class="form-control"> {% endmacro %}
- 调用宏
{{ 宏的名字('name' value='zs')}}
这会输出
<input type="text" name="name" value="zs" class="form-control">
使用方式二
把宏单独抽取出来,封装成html文件,其它模板中导入使用,文件名可以自定义macro.html,其内部代码如下:
{% macro function(type='text', name='', value='') %} <input type="{{type}}" name="{{name}}" value="{{value}}" class="form-control"> {% endmacro %}
在其它模板文件中先导入,再调用
{% import 'macro.html' as func %}
{% func.function() %}
创建一个test7.py的项目
from flask import Flask,render_template app = Flask(__name__) @app.route('/') def demo(): return render_template('temp05.html') if __name__ == '__main__': app.run(debug=True)
创建一个temp05.html的模板:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% macro input(name, type='text', placeholder='') %} <input name="{{ name }}" type="{{ type }}" placeholder="{{ placeholder }}"> {% endmacro %} 使用宏: {{ input('name',placeholder='请输入内容') }} </body> </html>
运行项目

把宏单独抽取出来,封装成html文件,其它模板中导入使用
创建一个macro.html宏的基类模板
{% macro input(name, type='text', placeholder='') %} <input name="{{ name }}" type="{{ type }}" placeholder="{{ placeholder }}"> {% endmacro %}
创建一个temp06.html的模板用来导入macro.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% import 'macro.html' as function %} 使用宏: {{ function.input('name',placeholder='请输入内容') }} </body> </html>
创建一个test8.py的项目
from flask import Flask,render_template app = Flask(__name__) @app.route('/') def demo(): return render_template('temp06.html') if __name__ == '__main__': app.run(debug=True)
运行项目

模板继承
模板继承是为了重用模板中的公共内容。一般Web开发中,继承主要使用在网站的顶部菜单、底部。这些内容可以定义在父模板中,子模板直接继承,而不需要重复书写。
- ````标签定义的内容
- 相当于在父模板中挖个坑,当子模板继承父模板时,可以进行填充。
- 子模板使用extends指令声明这个模板继承自哪个模板
- 父模板中定义的块在子模板中被重新定义,在子模板中调用父模板的内容可以使用super()
父模板
base.html
{% block top %}
顶部菜单
{% endblock top %}
{% block content %}
{% endblock content %}
{% block bottom %}
底部
{% endblock bottom %}
子模板
extends指令声明这个模板继承自哪
{% extends 'base.html' %}
{% block content %}
需要填充的内容
{% endblock content %}
模板继承使用时注意点:
- 不支持多继承
- 为了便于阅读,在子模板中使用extends时,尽量写在模板的第一行。
- 不能在一个模板文件中定义多个相同名字的block标签。
- 当在页面中使用多个block标签时,建议给结束标签起个名字,当多个block嵌套时,阅读性更好。
创建一个base.html的文件
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% block top %} 欢迎来到黑马 {% endblock %}<br/> {% block content %} 我是父模板中的内容 {% endblock %}<br/> {% block bottom %} <a href="http://www.itheima.com">关于我们</a> {% endblock %} </body> </html>
创建一个temp07.html文件
{% extends 'base.html' %} {% block content %} 我是子页面<br/> <p>super可以把父模板中这块区域的内容显示出来</p> {{ super() }} {% endblock content %}
创建一个test9.py的项目
from flask import Flask,render_template
app = Flask(__name__)
@app.route('/')
def demo():
return render_template('temp07.html')
if __name__ == '__main__':
app.run(debug=True)
运行项目

包含
Jinja2模板中,除了宏和继承,还支持一种代码重用的功能,叫包含(Include)。它的功能是将另一个模板整个加载到当前模板中,并直接渲染。
- include的使用
{% include 'hello.html' %}
包含在使用时,如果包含的模板文件不存在时,程序会抛出TemplateNotFound异常,可以加上 ignore missing 关键字。如果包含的模板文件不存在,会忽略这条include语句。
- include的使用加上关键字ignore missing
{% include 'hello.html' ignore missing %}
宏、继承、包含:
- 宏(Macro)、继承(Block)、包含(include)均能实现代码的复用。
- 继承(Block)的本质是代码替换,一般用来实现多个页面中重复不变的区域。
- 宏(Macro)的功能类似函数,可以传入参数,需要定义、调用。
- 包含(include)是直接将目标模板文件整个渲染出来。
Flask特有的变量和函数
不需要视图函数传送,你可以在自己的模板中访问一些Flask默认内置的函数和对象
config
你可以从模板中直接访问Flask当前的config对象:
{{config.SQLALCHEMY_DATABASE_URI}}
sqlite:///database.db
request
就是flask中代表当前请求的request对象:
{{request.url}}
http://127.0.0.1
request常用的属性如下:

session
为Flask的session对象
{{session.new}}
True
url_for()
url_for会根据传入的路由器函数名,返回该路由对应的URL,在模板中始终使用url_for()就可以安全的修改路由绑定的URL,则不比担心模板中渲染出错的链接:
{{url_for('home')}}
/
如果我们定义的路由URL是带有参数的,则可以把它们作为关键字参数传入url_for(),Flask会把他们填充进最终生成的URL中:
{{ url_for('post', post_id=1)}}
/post/1
get_flashed_messages()
这个函数会返回之前在flask中通过flask()传入的消息的列表,flash函数的作用很简单,可以把由Python字符串表示的消息加入一个消息队列中,再使用get_flashed_message()函数取出它们并消费掉:
{%for message in get_flashed_messages()%}
{{message}}
{%endfor%}
创建一个test10.py的项目
# -*- coding:utf-8 -*- from flask import Flask,flash,render_template app = Flask(__name__) app.secret_key = 'sNoagPAysQlINJZhqQdPDO1IE//Tur0MxLg9Et9/kHIxx+VsVyhO4Fu4bQVr4SRO' @app.route('/') def demo(): flash(u'输入的内容有毛病') flash(u'输入的内容有毛病') flash(u'输入的内容有毛病') flash(u'输入的内容有毛病') return render_template('temp08.html') if __name__ == '__main__': app.run(debug=True)
创建一个temp08.html的模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> {% for message in get_flashed_messages() %} {{ message }} <br> {% endfor %} </body> </html>
运行项目

Web表单
web表单是web应用程序的基本功能。
它是HTML页面中负责数据采集的部件。表单有三个部分组成:表单标签、表单域、表单按钮。表单允许用户输入数据,负责HTML页面数据采集,通过表单将用户输入的数据提交给服务器。
在Flask中,为了处理web表单,我们一般使用Flask-WTF扩展,它封装了WTForms,并且它有验证表单数据的功能
WTForms支持的HTML标准字段
| 字段对象 | 说明 |
|---|---|
| StringField | 文本字段 |
| TextAreaField | 多行文本字段 |
| PasswordField | 密码文本字段 |
| HiddenField | 隐藏文件字段 |
| DateField | 文本字段,值为 datetime.date 文本格式 |
| DateTimeField | 文本字段,值为 datetime.datetime 文本格式 |
| IntegerField | 文本字段,值为整数 |
| DecimalField | 文本字段,值为decimal.Decimal |
| FloatField | 文本字段,值为浮点数 |
| BooleanField | 复选框,值为True 和 False |
| RadioField | 一组单选框 |
| SelectField | 下拉列表 |
| SelectMutipleField | 下拉列表,可选择多个值 |
| FileField | 文件上传字段 |
| SubmitField | 表单提交按钮 |
| FormField | 把表单作为字段嵌入另一个表单 |
| FieldList | 一组指定类型的字段 |
WTForms常用验证函数
| 验证函数 | 说明 |
|---|---|
| InputRequired | 确保字段中有数据 |
| DataRequired | 确保字段中有数据并且数据为真 |
| EqualTo | 比较两个字段的值,常用于比较两次密码输入 |
| Length | 验证输入的字符串长度 |
| NumberRange | 验证输入的值在数字范围内 |
| URL | 验证URL |
| AnyOf | 验证输入值在可选列表中 |
| NoneOf | 验证输入值不在可选列表中 |
使用Flask-WTF需要配置参数SECRET_KEY。
CSRF_ENABLED是为了CSRF(跨站请求伪造)保护。 SECRET_KEY用来生成加密令牌,当CSRF激活的时候,该设置会根据设置的密匙生成加密令牌。在HTML页面中直接写form表单:
在HTML页面中直接写form表单:
<form method='post'> <input type="text" name="username" placeholder='Username'> <input type="password" name="password" placeholder='password'> <input type="submit"> </form>
视图函数中获取表单数据:
from flask import Flask,render_template,request @app.route('/login',methods=['GET','POST']) def login(): if request.method == 'POST': username = request.form['username'] password = request.form['password'] print username,password return render_template('login.html',method=request.method)
接受前端页面表单传送的数据
创建一个test11.py的项目
# coding:utf8 import sys reload(sys) sys.setdefaultencoding('utf-8') from flask import Flask,render_template,request,flash app = Flask(__name__) app.secret_key='sdsafdgfdgfdgdfgdf' @app.route('/',methods=['get', 'post']) def index(): if request.method == "POST": name = request.form['username'] pwd1 = request.form['password'] pwd2 = request.form['password2'] if pwd1 != pwd2: flash('两次密码输入不一致') else: # 假装去注册 print name, pwd2 return render_template('temp09.html') if __name__ == '__main__': app.run(debug=True)
创建一个temo09.html的模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="post"> 账户:<input name="username" type="text" placeholder="请输入账户"><br/> <br> 密码:<input name="password" type="password" placeholder="请输入密码"><br/> <br> 确认密码:<input name="password2" type="password" placeholder="请输入密码"><br/> <br> <input type="submit" value="注册"> {% for message in get_flashed_messages() %} {{ message }} {% endfor %} </form> </body> </html>
运行项目,分别在表单中输入密码一致和不一致的情况
使用Flask-WTF实现表单
创建一个test12.py的项目
# coding:utf8 from flask import Flask, render_template from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, SubmitField import sys reload(sys) sys.setdefaultencoding('utf8') app = Flask(__name__) app.secret_key = 'sdsafdgfdgfdgdfgdf' # 创建一个自定义表单的类 class RegisterForm(FlaskForm): username = StringField(label='账户:') password = PasswordField(label='密码:') password2 = PasswordField(label='确认密码:') submit = SubmitField(label='注册') @app.route('/', methods=['get', 'post']) def demo(): form = RegisterForm() return render_template('temp10.html', form=form) if __name__ == '__main__': app.run(debug=True)
创建一个temp10.html模板
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="post"> {{ form.csrf_token() }} {{ form.username.label }}{{ form.username }}<br/> {{ form.password.label }}{{ form.password }}<br/> {{ form.password2.label }}{{ form.password2 }}<br/> {{ form.submit }}<br/> </form> </body> </html>
启动项目

在Flask-WTF实现的表单中添加验证
from wtforms.validators 导入需要验证的函数
在项test12.py的项目中添加表单验证
# coding:utf8 from flask import Flask, render_template,request,flash from flask_wtf import FlaskForm from wtforms import StringField, PasswordField, SubmitField # 添加表单认证 from wtforms.validators import DataRequired, EqualTo import sys reload(sys) sys.setdefaultencoding('utf8') app = Flask(__name__) app.secret_key = 'sdsafdgfdgfdgdfgdf' # 创建一个自定义表单的类 class RegisterForm(FlaskForm): username = StringField(label='账户:', validators=[DataRequired('请输入账户名')], render_kw={'placeholder': '请输入账户'}) password = PasswordField(label='密码:', validators=[DataRequired('请输入密码')], render_kw={'placeholder': '请输入密码'}) password2 = PasswordField(label='确认密码:', validators=[DataRequired('请输入确认密码'), EqualTo('password','两次密码输入不一致')], render_kw={'placeholder': '请输入确认密码'}) submit = SubmitField(label='注册') @app.route('/', methods=['get', 'post']) def demo(): form = RegisterForm() if form.validate_on_submit(): username = request.form['username'] password = request.form['password'] password2 = request.form['password2'] print username, password, password2 else: if request.method == 'POST': f = form print f for value in form.errors.values(): flash(value[0]) return render_template('temp10.html', form=form) if __name__ == '__main__': app.run(debug=True)
在temp10.html中添加
{% for message in get_flashed_messages() %}
{{ message }}
{% endfor %}
完整代码
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form method="post"> {{ form.csrf_token() }} {{ form.username.label }}{{ form.username }}<br/> {{ form.password.label }}{{ form.password }}<br/> {{ form.password2.label }}{{ form.password2 }}<br/> {{ form.submit }}<br/> {% for message in get_flashed_messages() %} {{ message }} {% endfor %} </form> </body> </html>
可以在前端的表单中 ,少输入值,密码输入不一致,等查看现象..
对test12.py的项目部分代码解释
username = StringField(label='账户:', validators=[DataRequired('请输入账户名')], render_kw={'placeholder': '请输入账户'})
StringField() WTForms支持的HTML标准字段,是一个文本字段。它的一个参数render_kw = {" ":" "},可以给表单添加属性,这里给表单添加的是placeholder的属性
validators=[ ] 这个是验证器,是一个列表,可以传入多个验证的函数
验证函数 DataRequired('')确保字段中有数据并且数据为真,可以接受一个参数,及验证出错的信息,如:“请输入账户名”
if form.validate_on_submit():
上面代码的意思是,如果表单在提交的时候是有效的,即所有的验证都通过。
if request.method == 'POST': f = form print f for key in form.errors: flash(form.errors[key][0]) # 无效的 # flash('输入的内容有毛病')
上面的代码可以通过打断点来查看f的值
在表单中两次密码输入的不一致,查看断点的信息

可以看出errors是一个字典,它的值是一个列表,通过form.errors[key][0]即可取出它的错误信息

浙公网安备 33010602011771号