欢迎来到 Jinja2
Jinja2 是一个现代的,设计者友好的,仿照 Django 模板的 Python 模板语言。 它速度快,被广泛使用,并且提供了可选的沙箱模板执行环境保证安全:
<title>{% block title %}{% endblock %}</title>
<ul>
{% for user in users %}
<li><a href="{{ user.url }}">{{ user.username }}</a></li>
{% endfor %}
</ul>
特性:
- 沙箱中执行
- 强大的 HTML 自动转义系统保护系统免受 XSS
- 模板继承
- 及时编译最优的 python 代码
- 可选提前编译模板的时间
- 易于调试。异常的行数直接指向模板中的对应行。
- 可配置的语法
Jinja2 文档
介绍
Jinja2 需要至少 Python 2.4 版本来运行。
安装
sudo easy_install Jinja2
sudo pip install Jinja2
基本 API 使用
通过创建一个 Template 的实例,你会得到一个新的模板对象,提供一 个名为 render() 的方法,该方法在有字典或关键字参数时调用 扩充模板。字典或关键字参数会被传递到模板,即模板“上下文”。
API
基础
Jinja2 使用一个名为 Environment 的中心对象。这个类的实例用于存储配置、全局对象,并用于从文件系统或其它位置
加载模板。
大多数应用在应用初始化时创建一个 Environment 对象,并用它加载模板。
配置 Jinja2 为你的应用加载文档的最简单方式看起来大概是这样:
from jinja2 import Environment, PackageLoader
# 一个在 yourapplication python 包中的 templates 文件夹中寻找模板的加载器
env = Environment(loader=PackageLoader('yourapplication', 'templates'))
#
template = env.get_template('mytemplate.html')
template.render(the='variables', go='here')
Unicode
Jinja2 内部使用 Unicode ,这意味着你需要向渲染函数传递 Unicode 对象或只包含 ASCII 字符的字符串。此外,换行符按照默认 UNIX 风格规定行序列结束( \n )。
要显式使用一个 Unicode 字符串,你需要给字符串字面量加上 u 前缀: u'Hänsel und Gretel sagen Hallo'
。
>>> m = Template(u"{% set a, b = 'foo', 'föö' %}").module
>>> m.a
'foo'
>>> m.b
u'f\xf6\xf6'
高层 API
class jinja2.Environment([options])
block_start_string
: Defaults to ‘{%’block_end_string
: Defaults to ‘%}’variable_start_string
: Defaults to ‘{{’variable_end_string
: Defaults to ‘}}’comment_start_string
: Defaults to ‘{#’comment_end_string
: Defaults to ‘#}’- …
shared
如果模板通过 Template 构造函数创建,会自动创建一个环境。这 些环境被创建为共享的环境,这意味着多个模板拥有相同的匿名环境。对所有 模板共享环境,这个属性为 True ,反之为 False 。
sandboxed
如果环境在沙箱中,这个属性为 True 。沙箱模式见文档中的 SandboxedEnvironment 。
filters,tests,globals,overlay 略…
undefined([hint, obj, name, exc])
为 name 创建一个新 Undefined 对象。
# some_name 未被定义
return environment.undefined(name='some_name')
# obj.name 未被定义
if not hasattr(obj, 'attr'):
return environment.undefined(obj=obj, name='attr')
# 例如 first() 过滤器 用这种方法创建一个未定义对象:
return environment.undefined('no first item, sequence was empty')
add_extension
compile_expression(source, undefined_to_none=True)
>>> env = Environment()
>>> expr = env.compile_expression('foo == 42')
>>> expr(foo=23)
False
>>> expr(foo=42)
True
class jinja2.Template
class jinja2.environment.TemplateStream
…
沙箱
Jinja2 沙箱用于为不信任的代码求值。访问不安全的属性和方法是被禁止的。
模板设计者文档
概要
模板仅仅是文本文件。它可以生成任何基于文本的格式(HTML、XML、CSV、LaTex 等等)。 它并没有特定的扩展名, .html 或 .xml 都是可以的。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<head>
<title>My Webpage</title>
</head>
<body>
<ul id="navigation">
{% for item in navigation %}
<li><a href="{{ item.href }}">{{ item.caption }}</a></li>
{% endfor %}
</ul>
<h1>My Webpage</h1>
{{ a_variable }}
</body>
</html>
应用开发者也会把语法从 {% foo %} 改成 <% foo %> 或类似的东西。
这里有两种分隔符: {% … %} 和 {{ … }} 。前者用于执行诸如 for 循环 或赋值的语句,后者把表达式的结果打印到模板上。
变量
{{ foo.bar }}
{{ foo['bar'] }}
过滤器
变量可以通过 过滤器 修改。过滤器与变量用管道符号( | )分割,并且也 可以用圆括号传递可选参数。
多个过滤器可以链式调用,前一个过滤器的输出会被作为 后一个过滤器的输入。
例如
- {{ name|striptags|title }} 会移除 name 中的所有 HTML 标签并且改写 为标题样式的大小写格式。
- 过滤器接受带圆括号的参数,如同函数调用。这个例子会 把一个列表用逗号连接起来: {{ list|join(', ') }} 。
内置过滤器
- abs(number)
- attr(obj, name): Get an attribute of an object. foo|attr(“bar”) works like foo[“bar”] just that always an attribute is returned and items are not looked up.
- batch(value, linecount, fill_with=None)
<table>
{%- for row in items|batch(3, ' ') %}
<tr>
{%- for column in row %}
<td>{{ column }}</td>
{%- endfor %}
</tr>
{%- endfor %}
</table>
- indent(s, width=4, indentfirst=False) : Return a copy of the passed string, each line indented by 4 spaces. The first line is not indented.
测试
测试也可以接受参数。如果测试只接受一个参数,你可以省去括号来分组它们。例如, 下面的两个表达式做同样的事情:
{% if loop.index is divisibleby 3 %}
{% if loop.index is divisibleby(3) %}
内置测试清单
空白控制
默认配置中,模板引擎不会对空白做进一步修改,所以每个空白(空格、制表符、换行符 等等)都会原封不动返回。如果应用配置了 Jinja 的 trim_blocks ,模板标签后的 第一个换行符会被自动移除.
你也可以手动剥离模板中的空白。当你在块(比如一个 for 标签、一段注释或变 量表达式)的开始或结束放置一个减号( - ),可以移除块前或块后的空白:
{% for item in seq -%}
{{ item }}
{%- endfor %}
转义
有时想要或甚至必要让 Jinja 忽略部分,不会把它作为变量或块来处理。例如,如果 使用默认语法,你想在在使用把 {{ 作为原始字符串使用,并且不会开始一个变量 的语法结构,你需要使用一个技巧。
最简单的方法是在变量分隔符中( {{ )使用变量表达式输出:{{ '{{' }}
对于较大的段落,标记一个块为 raw 是有意义的。例如展示 Jinja 语法的实例, 你可以在模板中用这个片段:
{% raw %}
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
{% endraw %}
行语句
如果应用启用了行语句,就可以把一个行标记为一个语句。例如如果行语句前缀配置为 # ,下面的两个例子是等价的:
<ul>
# for item in seq
<li>{{ item }}</li>
# endfor
</ul>
<ul>
{% for item in seq %}
<li>{{ item }}</li>
{% endfor %}
</ul>
行语句前缀可以出现在一行的任意位置,只要它前面没有文本。为了语句有更好的可读 性,在块的开始(比如 for 、 if 、 elif 等等
)以冒号结尾:
提示
若有未闭合的圆括号、花括号或方括号,行语句可以跨越多行:
<ul>
# for href, caption in [('index.html', 'Index'),
('about.html', 'About')]:
<li><a href="{{ href }}">{{ caption }}</a></li>
# endfor
</ul>
从 Jinja 2.2 开始,行注释也可以使用了。例如如果配置 ## 为行注释前缀
, 行中所有 ## 之后的内容(不包括换行符)会被忽略:
# for item in seq:
<li>{{ item }}</li> ## this comment is ignored
# endfor
模板继承
基本模板
个模板,我们会把它叫做 base.html ,定义了一个简单的 HTML 骨架文档,你可 能使用一个简单的两栏页面。
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="en">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
{% block head %}
<link rel="stylesheet" href="style.css" />
<title>{% block title %}{% endblock %} - My Webpage</title>
{% endblock %}
</head>
<body>
<div id="content">{% block content %}{% endblock %}</div>
<div id="footer">
{% block footer %}
© Copyright 2008 by <a href="http://domain.invalid/">you</a>.
{% endblock %}
</div>
</body>
在本例中, {% block %} 标签定义了四个字幕版可以填充的块。
子模板
{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
{{ super() }}
<style type="text/css">
.important { color: #336699; }
</style>
{% endblock %}
{% block content %}
<h1>Index</h1>
<p class="important">
Welcome on my awesome homepage.
</p>
{% endblock %}
{% extend %} 标签是这里的关键。它告诉模板引擎这个模板“继承”另一个模板。
当模板系统对这个模板求值时,首先定位父模板。 extends 标签应该是模板中的第一个 标签。
例FileSystemLoader 允许你用文件名访 问其它模板。你可以使用斜线访问子目录中的模板:
{% extends "layout/default.html" %}
Super 块
可以调用 super 来渲染父级块的内容。这会返回父级块的结果:
{% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ super() }}
{% endblock %}
命名块结束标签
Jinja2 允许你在块的结束标签中加入的名称来改善可读性:
{% block sidebar %}
{% block inner_sidebar %}
...
{% endblock inner_sidebar %}
{% endblock sidebar %}
嵌套块和作用域
{% for item in seq %}
<li>{% block loop_item %}{{ item }}{% endblock %}</li>
{% endfor %}
HTML 转义
控制结构清单
For
if
宏
宏类似常规编程语言中的函数。它们用于把常用行为作为可重用的函数,取代 手动重复的工作。
如果宏在不同的模板中定义,你需要首先使用 import 。