Table of Contents
01模板与自定义过滤器
Jinja2模板
from flask import render_template |
{{name}} |
传单个值
return render_template('index.html', name=result) |
Kv方式多值
data={ "name":"python", "age":18 } return render_template('index.html', **data) |
传其他类型变量:
data={ "name":"python", "my_dict":{"city":"bj"}, "my_int":18, "my_list":[1,2,3], } return render_template('index.html', **data) |
<p>name = {{ name }}</p> <p>my_dict: {{ my_dict["city"] }}</p> <p>my_dict: {{ my_dict.city }}</p> <p>my_list: {{ my_list }}</p> <p>my_list[my_int]: {{ my_list[my_int] }}</p> |
过滤器
字符串过滤器:Safe禁用转义
{{ text | safe }} |
列表过滤器:length获取列表长度
{{ data | safe | length }} |
这功能厉害是厉害,但后端的事还要跑到前端来做么
自定义的过滤器如果和内置过滤器重名,会覆盖内置
return render_template('index.html', **data) def list_step_2(li): return li[::2]
#注册过滤器,使用名不是函数名而是注册名 app.add_template_filter(list_step_2, "li2") |
02表单WTF原理简介
经典方式:
<form method="post"> <input type="text" name="username" placeholder="Username"> <input type="submit"> </form> |
@app.route('/login',methods=['GET','POST']) def login(): if request.methods == 'POST': username=request.form['username'] print username return "success" else: return render_template('login.html') |
引入Flask-WTF,抽象出一个表单类
需要时创建该类的对象,在模板中使用该对象的属性。可帮助CSRF跨站请求伪造攻击校验
(疑问:前端直接使用对象属性对style设置会不会有影响)
pip install Flask-WTF |
03 表单模型类与模板使用
from flask_wtf import FlaskForm |
WTForms支持html中的大部分字段Type
from wtforms import StringField,PasswordField,SubmitField |
自带有常用的验证函数(DataRequired不为空,EqualTo两值相等)
from wtforms.validators import DataRequired, EqualTo |
CSRF校验依赖:请求cookie密钥,请求体中值
app.config["SECRET_KEY"]="miyue123" |
定义表单模型类:
class RegisterForm(object): user_name=StringField(label=u"用户名",validators=[DataRequired(u"用户名不能为空")]) password=PasswordField(label=u"密码",validators=[DataRequired(u"密码不能为空")]) password2=PasswordField(label=u"确认密码",validators=[DataRequired(u"确认密码不能为空"),EqualTo("password","两次密码不一致")]) submit=SubmitField(label=u"提交") |
Label为说明文字,validators为校验器,验证函数DataRequired内传入提示信息,EqualTo还需要传入比较的字段名
视图函数使用Form类的对象:
@app.route('/register',methods=['GET','POST']) def register(): form=RegisterForm() return render_template('register.html',form=form) |
前端:
<form method="post"> {{form.user_name.label}} <p>{{form.user_name}}</p> {%for msg in form.user_name.errors%} <p>{{msg}}</p> {%endfor%} {{form.submit}} </form> |
04表单接收检验参数
不管是get还是post都需要创建表单对象(form=RegisterForm()),flask会把前端发送的数据存放到对象中。可以省略request对get与post判断
判断form中的数据是否合理:
form.validate_on_submit() |
如果form中的数据完全满足,返回真
Get方式访问时,此处数据空,不为真,只需判断为真时提取数据处理
user_name=form.user_name.data |
CSRF的密钥在表单中也要带
{{form.csrf_token}} |
@app.route('/register',methods=['GET','POST']) def register(): form=RegisterForm() if form.validate_on_submit(): user_name=form.user_name.data print(user_name) session["user_name"]=user_name return redirect(url_for("index")) return render_template('register.html',form=form) |
<form method="post"> {{form.csrf_token}} {{form.user_name.label}} <p>{{form.user_name}}</p> {%for msg in form.user_name.errors%} <p>{{msg}}</p> {%endfor%} {{form.submit}} </form> |
05
因为提交后form中已有数据,所以再次进入填写页面,渲染的用户名会保留上次填写的用户名
06模板宏
在模板中将重复出现的代码定义成宏以复用
{% macro input() %} <input type="text" value="" size="30"> {% endmacro %} |
{{ input() }} |
传入参数
{% macro input(type,value,size) %} <input type="{{type}}" value="{{value}}" size="{{size}}"> {% endmacro %} |
{{ input("password","",50) }} |
默认参数
{% macro input(type="text",value="",size=30) %} <input type="{{type}}" value="{{value}}" size="{{size}}"> {% endmacro %} |
{{ input() }} |
07宏定义在外部
单独建一个文件,只保留宏定义
{% macro input(type="text",value="",size=30) %} <input type="{{type}}" value="{{value}}" size="{{size}}"> {% endmacro %} |
在模板中导入
{% import 'macro.html' as func %} |
{{ func.input() }} |
08继承、闪现
扩展父模板:父模板挖空,子模版继承,填空
{% extends 'base.html' %} {% block content %} {% endblock content %} |
包含子模板:
{% include 'hello.html' %} |
特殊变量和方法:config、request、url_for也都能在模板中使用
Flash提供消息数据:
通过flash()传入信息列表,把消息加入到消息队列(存到session)
from flask import flash app.config["SECRET_KEY"]="miyue123" |
flash("flash message") |
get_flashed_messages()取出
{%for msg in get_flashed_messages()%} <p>{{msg}}</p> {% endfor %} |