之前已经总结过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>
    &#123;% if user is defined() %&#125;
        <h1> Hello &#123;&#123; user &#125;&#125; !</h1>
    &#123;% else %&#125;
        <h1> Gun !</h1>
    &#123;% endif %&#125;
</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或者&#123;% autoescape false %&#125;&#123;% endautoescape %&#125;关闭转义环境

  • safe过滤器: 过滤器safe在源码中是将对象转换成一个Mark_up类的对象并实现了__html__方法,所以数据对象就被标记为安全然后渲染到前端
  • autoescape: 将对象处于一个没有转义的环境下直接渲染到前端,跟__html__没有关系

模板继承&include&宏

之前在jinja语法中写过了,在这就简单记下

模板继承

1
2
3
4
5
&#123;&#123; extends "layout.html" &#125;&#125;
&#123;&#123; block content &#125;&#125;
    &#123;&#123; var1 &#125;&#125;
    &#123;&#123; fun(a,b)&#125;&#125;
&#123;&#123; endblock &#125;&#125;

include模板

包含的模板会被传递到当前的上下文,使用import的话就不会。导入不会像包含被缓存,因为导入经常只作为容纳宏的模块

1
&#123;% include 'header.html' without context %&#125;

宏其实就类似程序中的function,用来替代重复性操作

1
2
3
4
5
6
7
8
<!-- 定义 -->
&#123;% macro input(name, value='', type='text', size=20) -%&#125;
    <input type="&#123;&#123; type &#125;&#125;" name="&#123;&#123; name &#125;&#125;" value="&#123;&#123;
        value|e &#125;&#125;" size="&#123;&#123; size &#125;&#125;">
&#123;%- endmacro %&#125;
<!-- 使用 -->
<p>&#123;&#123; input('username') &#125;&#125;</p>
<p>&#123;&#123; input('password', type='password') &#125;&#125;</p>

两个特殊装饰器

@app.template_globle

这个装饰器可以使所有的模板都可以直接调用被装饰的函数

1
2
3
@app.template_global()
def hi(x, y):
    return str(x) + str(y)
1
<h1>&#123;&#123; hi('hello', 'world')&#125;&#125;</h1>

@app.template_filter

这个装饰器下的函数可以方便测试表达式,比如IF判断&#123;&#123; if a|fun(b,c) &#125;&#125;

1
2
3
@app.template_filter()
def hello(a, b, c):
    return a - b - c
1
<h2>&#123;&#123; 1|hello(2, 3) &#125;&#125;</h2>