之前已经总结过Jinja2了,这里主要总结在Falsk中的一些东西。包括以下方面
- 模板的目录结构设计
- 常用的模块
- HTML转义
- 特殊装饰器
模板的目录设计
没有绝对答案,从别人博客复制一个结构又加了一点补充,更详尽的可以参考他的博客
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
| - projectName
| - app //程序包
| - templates //jinjia2模板
| - layout.html
| - index.html
| - about.html
| - profile/
| - layout.html
| - index.html
| - photos.html
|- admin/
| - layout.html
| - index.html
| - analytics.html
|- static //css,js 图片等静态文件
| - main //py程序包 ,可以有多个这种包,每个对应不同的功能
| - __init__.py
|- errors.py
|- forms.py
|- views.py
|- __init__.py
|- email.py //邮件处理程序
|- models.py //数据库模型
|- migrations //数据迁移文件夹
| - tests //单元测试
|- __init__.py
|- test*.py //单元测试程序,可以包含多个对应不同的功能点测试
|- venv //虚拟环境
|- requirements.txt //列出了所有依赖包以及版本号,方便在其他位置生成相同的虚拟环境以及依赖
|- config.py //全局配置文件,配置全局变量
|
常用的模块
1
2
3
4
5
6
7
8
9
|
from flask import Flask,render_template
@app.route('/about')
def about():
return render_template('about.html',user='Gourds')
"""
render_template参数说明:
第一个参数是模板名称,默认会在当前路径下的templates中查找
user='Gourds',其中左边data1表示模板中的占位符,右边表示在当前视图中的变量
"""
|
如下就是HTML的例子(定义user返回hello不然返回gun)。变量表达式使用{{ }}
,控制语句使用{% %}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Gourds</title>
</head>
<body>
{% if user is defined() %}
<h1> Hello {{ user }} !</h1>
{% else %}
<h1> Gun !</h1>
{% endif %}
</body>
</html>
|
HTML自动转义
jinja2默认情况下实惠自动转义的。如下,会被自动转义
1
2
3
|
@app.route('/index')
def index():
return '<h1> Welcome %s </h1>' % '<em>Gourds<em>'
|
不过有时候你可能就是想让输出这个,在Flask中可以使用Marup
实现
1
2
3
4
|
from flask import Markup
@app.route('/index')
def index():
return Markup('<h1> Welcome %s </h1>') % '<em>Gourds<em>'
|
自动转义的原因
原因:被渲染到页面的对象中没有实现__html__
方法的对象。换句话说,就是假设一个对象实现了__html__
方法那么这个对象就是安全的,jinja2模板就不会将它转义,即使他就是个恶意的脚本,那么为了防止被恶意脚本攻击,jinja2模板默认开启了自动转义,频繁的自动转义是会大量的消耗资源的,所以在确定该数据是安全的情况下可以用过滤器|safe
或者{% autoescape false %}{% endautoescape %}
关闭转义环境
- safe过滤器:
过滤器safe在源码中是将对象转换成一个
Mark_up
类的对象并实现了__html__
方法,所以数据对象就被标记为安全然后渲染到前端
- autoescape:
将对象处于一个没有转义的环境下直接渲染到前端,跟
__html__
没有关系
模板继承&include&宏
之前在jinja语法中写过了,在这就简单记下
模板继承
1
2
3
4
5
|
{{ extends "layout.html" }}
{{ block content }}
{{ var1 }}
{{ fun(a,b)}}
{{ endblock }}
|
include模板
包含的模板会被传递到当前的上下文,使用import
的话就不会。导入不会像包含被缓存,因为导入经常只作为容纳宏的模块
1
|
{% include 'header.html' without context %}
|
宏
宏其实就类似程序中的function,用来替代重复性操作
1
2
3
4
5
6
7
8
|
<!-- 定义 -->
{% macro input(name, value='', type='text', size=20) -%}
<input type="{{ type }}" name="{{ name }}" value="{{
value|e }}" size="{{ size }}">
{%- endmacro %}
<!-- 使用 -->
<p>{{ input('username') }}</p>
<p>{{ input('password', type='password') }}</p>
|
两个特殊装饰器
@app.template_globle
这个装饰器可以使所有的模板都可以直接调用被装饰的函数
1
2
3
|
@app.template_global()
def hi(x, y):
return str(x) + str(y)
|
1
|
<h1>{{ hi('hello', 'world')}}</h1>
|
@app.template_filter
这个装饰器下的函数可以方便测试表达式,比如IF判断{{ if a|fun(b,c) }}
1
2
3
|
@app.template_filter()
def hello(a, b, c):
return a - b - c
|
1
|
<h2>{{ 1|hello(2, 3) }}</h2>
|