API

本页文档描述Jinja2的API而不是模板语言。这对给应用实现模板接口的人员,而不是创建Jinja2模板的人员,是最有用的参考。

基本用法

Jinja2用到一个中心对象,叫做模板Environment这个类的实例用于存储配置和全局对象,并用于从文件系统或其它位置加载模板。即使你是使用Template类的构造函数从字符串来创建模板,还是会为你自动创建一个environment,尽管它是共享的。

大多数应用在应用初始化时创建一个Environment 对象,并用它加载模板。然而,在某些情况下,如果用到多个不同的配置,拥有多个并列的environment是有很有用的。

配置Jinja2为你的应用加载模板的最简单方式看起来大概是这样:

from jinja2 import Environment, PackageLoader
env = Environment(loader=PackageLoader('yourapplication', 'templates'))

这会创建一个默认设定下的模板环境,和一个在yourapplication python 包中的templates文件夹中寻找模板的加载器。有多个不同的加载器可以使用,如果你需要从数据库或其它资源加载模板,你也可以自己写一个。

若要从这个环境中加载模板,你只需要调用get_template()方法,它会返回已加载的Template

template = env.get_template('mytemplate.html')

若要用一些变量来渲染它,只需调用render()方法:

print template.render(the='variables', go='here')

使用一个模板加载器,而不是向 TemplateEnvironment.from_string() 传递字符串,有许多好处。 除了使用上便利, 也使得模板继承成为可能。

Unicode

Jinja2 内部使用 Unicode ,这意味着你需要向渲染函数传递 Unicode 对象或只包含 ASCII 字符的字符串。 此外,换行符按照默认 UNIX 风格规定行序列结束( \n )。

Python 2.x 支持两种表示字符串对象的方法。 一种是 str 类型,另一种是 unicode 类型,它们都继承于 basestring 类型。 不幸的是,默认的 str 不 应该用于存储基于文本的信息,除非只用到 ASCII 字符。 在 Python 2.6 中,可以 在模块层指定 unicode 为默认值,而在 Python 3 中会是默认值。

要显式使用一个 Unicode 字符串,你需要给字符串字面量加上 u 前缀: u'Hänsel und Gretel sagen Hallo' 这样 Python 会用当前模块的字符编码来 解码字符串,来把字符串存储为 Unicode 。 如果没有指定编码,它默认是ASCII,这意味着你不能使用任何非ASCII标识符。

在使用 Unicode 字面量的 Python 模块的首行或第二行添加下面的注释,来妥善设 置模块编码:

# -*- coding: utf-8 -*-

我们推荐为 Python 模块和模板使用 utf-8 编码,因为在 utf-8 中,可以表示 Unicode 中的每个字符,并且向后兼容 ASCII 。 对于 Jinja2 ,模板的默认编码 假定为 utf-8 。

用 Jinja2 来处理非 Unicode 数据是不可能的。 这是因为 Jinja2 已经在语言层 使用了 Unicode 。 例如 Jinja2 在表达式中把不间断空格视为有效的空格,这需要 获悉编码或操作一个 Unicode 字符串。

关于 Python 中 Unicode 的更多细节,请阅读完善的 Unicode documentation

另一件重要的事情是 Jinja2 如何处理模板中的字符串字面量。 原生实现会对所有 字符串字面量使用 Unicode ,但在过去这是有问题的,因为一些库显式地检查它 们的类型是否为 str 例如 datetime.strftime 不接受 Unicode 参数。 为了不彻底破坏它, Jinja2 对只有 ASCII 的字符串返回 str,而对其它返回 unicode:

>>> m = Template(u"{% set a, b = 'foo', 'föö' %}").module
>>> m.a
'foo'
>>> m.b
u'f\xf6\xf6'

上层API

上层API是你在应用中用于加载并渲染Jinja2模板的API。相反,底层API只在你想深入挖掘Jinja2或者开发扩展时有用。

class jinja2.Environment([options])

Environment是Jinja的核心组件。它包含重要的共享变量,如配置、filters、 测试、 全局变量以及其它变量。如果该类的实例不是共享的而且目前为止没有加载模板,则它们可以修改。如果第一个模板加载后修改environment,将导致意想不到的效果和未定义的行为。

下面是可用的初始化参数︰

block_start_string
标记块开始的字符串。默认为'{%'
block_end_string
标记块结束的字符串。默认为'%}'
variable_start_string
标记print语句开始的字符串。默认为'{{'
variable_end_string
标记print语句结束的字符串。默认为'}}'
comment_start_string
标记注释开始的字符串。默认为'{#'
comment_end_string
标记注释结束的字符串。默认为'#}'
line_statement_prefix
如果给出并且是一个字符串,将用作基于行的语句的前缀。另见行语句
line_comment_prefix

如果给出并且是一个字符串,将用作基于行的注释的前缀。另见行语句

版本2.2中新增。

trim_blocks
如果设置为True,块之后的第一行将删除(是块标签,不是变量标签!)。默认为False
lstrip_blocks
如果设置为True,行开始到块之间的空白和制表符将删除。默认为False
newline_sequence
开始新的一行的序列。必须是'\r''\n''\r\n'中的一个。默认为'\n',这对Linux和OS X系统以及Web应用都是一个有用的默认值。
keep_trailing_newline

渲染模板时,保留末尾的换行。默认为False,如果模板的末尾有一个换行,这将导致它被删除。

版本2.7中新增。

扩展
使用的Jinja扩展的一个列表。它可以是字符串形式的import路径或者扩展的类。更多信息参见扩展的文档
optimized
是否启用优化器?默认为True
未定义
Undefined或其子类,用于表示模板中的未定义值。
finalize
可用于在输出变量表达式的结果之前处理该变量表达式的可调用项。例如,可以将None隐式转换为空字符串。
autoescape

This will return the rendered template as unicode string. 有关自动转义的详细信息,请参阅Markup对于Jinja 2.4,这也可以是传递模板名称的可调用,并且必须返回TrueFalse取决于autoescape应该默认启用。

Changed in version 2.4: autoescape can now be a function

loader
此环境的模板加载器。
cache_size

缓存的大小。默认情况下,这是400,这意味着如果加载超过400个模板,加载器将清除最近最少使用的模板。如果缓存大小设置为0,模板将始终重新编译,如果缓存大小为-1,则不会清除缓存。

在版本2.8中已更改:缓存大小从低50增加到400。

auto_reload
一些加载器从模板源可能更改的位置(即:文件系统或数据库)加载模板。如果每次请求模板时将auto_reload设置为True(默认),加载程序将检查源是否已更改,如果是,则会重新加载模板。为了更高的性能,可以禁用它。
bytecode_cache

如果设置为字节码缓存对象,则此对象将为内部Jinja字节码提供缓存,以便如果不更改模板,则不必解析模板。

有关详细信息,请参见Bytecode Cache

shared

如果模板通过 Template 构造函数创建,会自动创建一个环境。 这些环境被创建为共享的环境,这意味着多个模板拥有相同的匿名环境。 对所有 模板共享环境,这个属性为 True ,反之为 False

sandboxed

如果环境在沙箱中,这个属性为 True 沙箱模式见文档中的 SandboxedEnvironment

filters

该环境的过滤器字典。 只要没有加载过模板,添加新过滤器或删除旧的都是 安全的。 自定义过滤器见 自定义过滤器 有效的过滤器名称见 标识符的说明

tests

该环境的测试函数字典。 只要没有加载过模板,修改这个字典都是安全的。 自定义测试见 see 自定义测试 有效的测试名见 标识符的说明

globals

一个全局变量字典。 这些变量在模板中总是可用。 只要没有加载过模板,修 改这个字典都是安全的。 更多细节见 全局命名空间 有效的 对象名见 标识符的说明

code_generator_class

用于代码生成的类。这在大多数情况下不应该更改,除非你需要修改模板编译的Python代码。

context_class

用于模板的上下文。这在大多数情况下不应该更改,除非你需要修改模板变量的内部处理。有关详细信息,请参见Context

overlay([options])

创建一个新的覆盖环境,它与当前环境共享所有数据,但缓存和覆盖属性除外。无法移除覆盖环境的扩展程序。覆盖环境会自动获取所链接的环境的所有扩展以及可选的额外扩展。

创建覆盖应在初始环境完全设置后进行。并非所有属性都是真正链接的,有些只是复制过来的,所以对原始环境的修改可能不会通过。

undefined([hint, obj, name, exc])

name 创建一个新 Undefined 对象。 这对可能为某些操作返回 未定义对象过滤器和函数有用。 除了 hint ,为了良好的可读性,所有参数 应该作为关键字参数传入。 如果提供了 hint ,它被用作异常的错误消息, 否则错误信息会由 objname 自动生成。 exc 为生成未定义对象而 不允许未定义的对象时抛出的异常。 默认的异常是 UndefinedError如果提供提示,则可以省略名称

创建一个未定义对象的最常用方法是只提供名称:

return environment.undefined(name='some_name')

这意味着名称 some_name 未被定义。 如果名称来自一个对象的属性,把 持有它的对象告知未定义对象对丰富错误消息很有意义:

if not hasattr(obj, 'attr'):
    return environment.undefined(obj=obj, name='attr')

更复杂的例子中,你可以提供一个 hint 。 例如 first() 过滤器 用这种方法创建一个未定义对象:

return environment.undefined('no first item, sequence was empty')

如果 nameobj 是已知的(比如访问了了一个属性),它应该传递给 未定义对象,即使提供了自定义的 hint 这让未定义对象有可能增强错误 消息。

add_extension(extension)

在创建环境后添加扩展。

版本2.5中的新功能。

compile_expression(source, undefined_to_none=True)

一个方便的帮助方法,返回一个可调用的接受在表达式中显示为变量的关键字参数。如果调用,它返回表达式的结果。

如果应用程序要在模板“配置文件”或类似情况下使用与Jinja相同的规则,这将非常有用。

用法示例:

>>> env = Environment()
>>> expr = env.compile_expression('foo == 42')
>>> expr(foo=23)
False
>>> expr(foo=42)
True

默认情况下,如果表达式返回未定义的值,则返回值将转换为这可以通过将undefined_to_none设置为False来更改。

>>> env.compile_expression('var')() is None
True
>>> env.compile_expression('var', undefined_to_none=False)()
Undefined

版本2.1中的新功能。

compile_templates(target, extensions=None, filter_func=None, zip='deflated', log_function=None, ignore_errors=True, py_compile=False)

找到加载器可以找到的所有模板,对它们进行编译,并将它们存储在target中。如果zip,而不是在zip文件中,模板将存储在一个目录中。 Example usage: 要切换到存储的算法,zip可以设置为'stored'

extensions and filter_func are passed to list_templates(). Each template returned will be compiled to the target folder or zipfile. 返回的每个模板将被编译到目标文件夹或zipfile。

默认情况下将忽略模板编译错误。如果提供日志功能,则记录错误。如果希望模板语法错误中止编译,您可以将ignore_errors设置为False,并且您将获得语法错误的异常。

如果py_compile设置为True .pyc文件将被写入目标,而不是标准的.py文件。这个标志在pypy和Python 3上不做任何事情,其中​​pyc文件本身不被拾取,并且没有多少好处。

版本2.4中的新功能。

extend(**attributes)

将项目添加到环境的实例(如果它们尚不存在)。这由extensions用于注册回调和配置值,而不会中断继承。

from_string sourceglobals = Nonetemplate_class = None

从字符串加载模板。这将解析给定的源并返回一个Template对象。

get_or_select_template(template_name_or_list, parent=None, globals=None)

Does a typecheck and dispatches to select_template() if an iterable of template names is given, otherwise to get_template().

版本2.3中的新功能。

get_template(name, parent=None, globals=None)

从加载器加载模板。如果配置了加载器,则此方法要求加载器获取模板并返回Template如果参数不是,则调用join_path()以在加载之前获取真实的模板名称。

全局变量参数可用于提供模板宽全局变量。这些变量在渲染时在上下文中可用。

If the template does not exist a TemplateNotFound exception is raised.

在版本2.4中更改:如果名称Template对象,则从函数不变返回。

join_path(template, parent)

与父级联接模板。默认情况下,所有查找都与加载器根相关,因此此方法返回模板参数不变,但如果路径应相对于父模板,则此函数可用于计算真实模板名称。

子类可以覆盖此方法并在此处实现模板路径连接。

list_templates(extensions=None, filter_func=None)

返回此环境的模板列表。这要求加载器支持加载器的list_templates()方法。

如果模板文件夹中除了实际模板之外还有其他文件,则可以过滤返回的列表。有两种方法:将扩展设置为模板的文件扩展名列表,或者可以提供一个可传递模板名称的可调用的filter_func返回True如果它应该在结果列表中结束。

如果加载器不支持,则会引发TypeError

版本2.4中的新功能。

select_template(names, parent=None, globals=None)

get_template()工作,但尝试一些模板,然后失败。如果它找不到任何模板,它将引发TemplatesNotFound异常。

版本2.3中的新功能。

在版本2.4中更改:如果名称包含Template对象,则从函数返回未更改。

class jinja2.Template

中央模板对象。此类表示已编译的模板,用于评估它。

通常,模板对象从Environment生成,但它也有一个构造函数,可以使用构造函数直接创建模板实例。它采用与环境构造函数相同的参数,但不可能指定加载器。

每个模板对象都有一些方法和成员,保证存在。但是,一个模板对象应该被认为是不可变的。不支持对对象的修改。

从构造函数而不是环境创建的模板对象确实具有指向可能与使用构造函数和兼容设置创建的其他模板共享的临时环境的环境属性。

>>> template = Template('Hello {{ name }}!')
>>> template.render(name='John Doe') == u'Hello John Doe!'
True
>>> stream = template.stream(name='John Doe')
>>> next(stream) == u'Hello John Doe!'
True
>>> next(stream)
Traceback (most recent call last):
    ...
StopIteration
globals

该模板的全局变量字典。 修改这个字典是不安全的,因为它可能与其它模板或 加载这个模板的环境共享。

name

模板的加载名。 如果模板从字符串加载,这个值为 None

filename

文件系统上的模板的文件名(如果从那里加载)。否则,这是

render([context])

此方法接受与dict构造函数相同的参数:A dict,dict子类或一些关键字参数。如果没有给出参数,上下文将为空。这两个调用相同:

template.render(knights='that say nih')
template.render({'knights': 'that say nih'})

该 bucket 的唯一键

generate([context])

对于非常大的模板,可以有用的是不立即呈现整个模板,但是评估每个语句在另一个语句之后并产生一个片段。这个方法基本上正是这样,并返回一个生成器,产生一个项目接一个作为unicode字符串。

It accepts the same arguments as render().

stream([context])

Works exactly like generate() but returns a TemplateStream.

make_module(vars=None, shared=False, locals=None)

此方法的工作原理类似于module属性时调用无参数,但它将评估模板在每个调用,而不是缓存它。它也可以提供一个dict然后用作上下文。参数与new_context()方法相同。

module

模板作为模块。这用于在模板运行时导入,但是如果想从Python层访问导出的模板变量也很有用:

>>> t = Template('{% macro foo() %}42{% endmacro %}23')
>>> str(t.module)
'23'
>>> t.module.foo() == u'42'
True
class jinja2.environment.TemplateStream

模板流非常像一个普通的python生成器,但它可以缓冲多个项目,以减少总迭代次数。默认情况下,输出是无缓冲的,这意味着对于模板中的每个未缓冲的指令,产生一个unicode字符串。

如果使用缓冲区大小5启用缓冲,则会将五个项目组合成一个新的Unicode字符串。这主要是有用的,如果你通过WSGI流动大模板到客户端,每次迭代后刷新。

disable_buffering()

禁用输出缓冲。

dump(fp, encoding=None, errors='strict')

将完整的流转储为文件或类似文件的对象。如果要在写入前指定编码,那么将写入默认的Unicode字符串。

用法示例:

Template('Hello {{ name }}!').stream(name='foo').dump('hello.html')
enable_buffering(size=5)

启用缓冲。缓冲区size项目,然后再生成它们。

自动绘制

版本2.4中的新功能。

从 Jinja 2.4 开始,自动转义的首选途径就是启用 自动转义扩展 并为自动转义配置一个合适的默认值。 这使得在单个模板基础上开关自动转义成为 可能(比如 HTML 对 文本)

这里有一个建议的设置,它支持对以'.html''.htm''.xml'结尾的模板进行自动转写默认为所有其他扩展:

def guess_autoescape(template_name):
    if template_name is None or '.' not in template_name:
        return False
    ext = template_name.rsplit('.', 1)[1]
    return ext in ('html', 'htm', 'xml')

env = Environment(autoescape=guess_autoescape,
                  loader=PackageLoader('mypackage'),
                  extensions=['jinja2.ext.autoescape'])

假设实现一个自动转义函数,确保你也视 None 为有效模板名接受。 这会在从字符 串生成模板时传递。

在模板内,可以使用自动缩放块(请参阅Autoescape Extension)暂时更改行为。

标识符注释

Jinja2 使用正规的 Python 2.x 命名规则。 有效的标识符必须匹配 [a-zA-Z_][a-zA-Z0-9_]* 事实上,当前不允许非 ASCII 字符。 这个限制可能 会在 Python 3 充分规定 unicode 标识符后消失。

过滤器和测试会在独立的命名空间中查找,与标识符语法有细微区别。 过滤器和测 试可以包含点,用于按主题给过滤器和测试分组。 例如,把一个名为 to.unicode 的函数添加到过滤器字典是完全有效的。 过滤器和测试标识符的正则表达式是 [a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*

未定义类型

这些类可以用作未定义类型。 Environment 的构造函数接受一个可以是 那些类或一个 Undefined 的自定义子类的 undefined 参数。 无论何时, 这些对象创建或返回时,模板引擎都不能查出其名称或访问其属性。 未定义值上的 某些操作之后是允许的,而其它的会失败。

最接近常规 Python 行为的是 StrictUndefined ,如果它是一个未定义对象, 它不允许除了测试之外的一切操作。

class jinja2.Undefined

默认未定义类型。 The default undefined type. This undefined type can be printed and iterated over, but every other access will raise an jinja2.exceptions.UndefinedError:

>>> foo = Undefined(name='foo')
>>> str(foo)
''
>>> not foo
True
>>> foo + 42
Traceback (most recent call last):
  ...
jinja2.exceptions.UndefinedError: 'foo' is undefined
_undefined_hint

None 或给未定义对象的错误消息 unicode 字符串。

_undefined_obj

None 或引起未定义对象创建的对象(例如一个属性不存在)。

_undefined_name

未定义变量/属性的名称,如果没有此类信息,留为 None

_undefined_exception

未定义对象想要抛出的异常。 这通常是 UndefinedErrorSecurityError 之一。

_fail_with_undefined_error * args** kwargs t5>

参数任意,调用这个方法时会抛出带有由未定义对象上存储的未定义 hint 生成的错误信息的 _undefined_exception 异常。

class jinja2.DebugUndefined

未定义,在打印时返回调试信息。

>>> foo = DebugUndefined(name='foo')
>>> str(foo)
'{{ foo }}'
>>> not foo
True
>>> foo + 42
Traceback (most recent call last):
  ...
jinja2.exceptions.UndefinedError: 'foo' is undefined
class jinja2.StrictUndefined

一个未定义的打印和迭代,以及布尔测试和各种比较。换句话说:除了检查是否使用定义的测试定义它,你可以不做任何事情。

>>> foo = StrictUndefined(name='foo')
>>> str(foo)
Traceback (most recent call last):
  ...
jinja2.exceptions.UndefinedError: 'foo' is undefined
>>> not foo
Traceback (most recent call last):
  ...
jinja2.exceptions.UndefinedError: 'foo' is undefined
>>> foo + 42
Traceback (most recent call last):
  ...
jinja2.exceptions.UndefinedError: 'foo' is undefined

还有一个工厂函数可以装饰未定义的对象,以便在故障时实现日志记录:

jinja2.make_logging_undefined(logger=None, base=None)

给定一个logger对象,这将返回一个新的未定义类,它将记录某些失败。它将记录迭代和打印。如果没有给出记录器,则创建默认记录器。

例:

logger = logging.getLogger(__name__)
LoggingUndefined = make_logging_undefined(
    logger=logger,
    base=Undefined
)

版本2.8中的新功能。

参数:
  • logger - 要使用的记录器。如果未提供,将创建默认日志记录器。
  • base - 添加记录功能的基类。默认为Undefined

未定义对象由调用 undefined 创建。

实施

Undefined 对象通过重载特殊的 __underscore__ 方法实现。 例如 默认的 Undefined 类实现 __unicode__ 为返回一个空字符串,但 __int__ 和其它会始终抛出异常。 你可以自己通过返回 0 实现转换为 int:

class NullUndefined(Undefined):
    def __int__(self):
        return 0
    def __float__(self):
        return 0.0

要禁用一个方法,重载它并抛出 _undefined_exception 因 为这在未定义对象中非常常用,未定义对象有辅助方法 _fail_with_undefined_error() 自动抛出错误。 这里的类工作类似于常规Undefined但是阻塞了迭代:

class NonIterableUndefined(Undefined):
    __iter__ = Undefined._fail_with_undefined_error

上下文

class jinja2.runtime.Context

模板上下文保存模板的变量。它存储传递给模板的值以及模板导出的名称。创建实例既不受支持也不有用,因为它在模板评估的各个阶段自动创建,不应手动创建。

上下文是不可变的。parent 的修改不得发生,并且只允许从生成的模板代码对vars进行修改。标记为contextfunction()的模板过滤器和全局函数获取作为第一个参数传递的活动上下文,并允许访问上下文只读。

The template context supports read only dict operations (get, keys, values, items, iterkeys, itervalues, iteritems, __getitem__, __contains__). 此外,还有一个resolve()方法不会与KeyError失败,但返回一个Undefined对象的缺失变量。

parent

一个模板查找的只读全局变量的词典。 这些变量可能来自另一个 Context ,或是 Environment.globals ,或是 Template.globals ,或指向一个由全局变量和传递到渲染函数的变 量联立的字典。 它一定不能被修改。

vars

模板局域变量。 这个列表包含环境和来自 parent 范围的上下文函数 以及局域修改和从模板中导出的变量。 模板会在模板求值时修改这个字典, 但过滤器和上下文函数不允许修改它。

environment

加载该模板的环境

exported_vars

这设定了所有模板导出量的名称。 名称对应的值在 vars 字典中。 可以用 get_exported() 获取一份导出变量的拷贝字典。

name

拥有此上下文的模板的载入名。

blocks

模板中块当前映射的字典。 字典中的键是块名称,值是注册的块的列表。 每个 列表的最后一项是当前活动的块(继承链中最新的)。

eval_ctx

当前的 求值上下文

call(callable, *args, **kwargs)

使用提供的参数和关键字参数调用callable,但如果可调用是contextfunction()environmentfunction(),则将活动上下文或环境注入为第一个参数。

get_all()

返回完整上下文的副本作为dict,包括导出的变量。

get_exported()

使用导出的变量获取新的dict。

resolve(key)

查找一个变量,例如__ getitem __get,但返回一个Undefined对象名称查找。

实施

Python frame 中的局域变量在函数中是不可变的,出于同样的原因,上下文是不可 变的。 Jinja2 和 Python 都不把上下文/ frame 作为变量的数据存储,而只作为 主要的数据源。

当模板访问一个模板中没有定义的变量时, Jinja2 在上下文中查找变量,此后, 这个变量被视为其是在模板中定义得一样。

加载器

加载器负责从诸如文件系统的资源加载模板。 环境会把编译的模块像 Python 的 sys.modules 一样保持在内存中。 sys.models 不同,无论如何这个 缓存默认有大小限制,且模板会自动重新加载。 所有的加载器都是 BaseLoader 的子类。 如果你想要创建自己的加载器,继 承 BaseLoader 并重载 get_source

class jinja2.BaseLoader

Libraries compatible with this class: 将此子类化并覆盖get_source以实现自定义加载机制。环境提供了一个get_template方法,调用加载器的加载方法来获取Template对象。

在文件系统上查找模板的加载器的一个非常基本的例子可能是这样的:

from jinja2 import BaseLoader, TemplateNotFound
from os.path import join, exists, getmtime

class MyLoader(BaseLoader):

    def __init__(self, path):
        self.path = path

    def get_source(self, environment, template):
        path = join(self.path, template)
        if not exists(path):
            raise TemplateNotFound(template)
        mtime = getmtime(path)
        with file(path) as f:
            source = f.read().decode('utf-8')
        return source, path, lambda: mtime == getmtime(path)
get_source(environment, template)

获取模板的源,文件名和重载帮助器。它传递了环境和模板名称,并且必须以(源, 文件名, uptodate)形式返回一个元组 t0 >或者如果找不到模板,则会引发TemplateNotFound错误。

Return the bytecode as string. 文件名应该是文件系统上文件的名称(如果从文件系统加载),否则如果没有使用加载器扩展,python使用文件名作为追踪。

元组中的最后一个项是uptodate函数。如果启用了自动重新加载,则始终调用它以检查模板是否已更改。不传递任何参数,因此函数必须在某处存储旧状态(例如在闭包中)。如果返回False,模板将被重新加载。

load(environment, name, globals=None)

加载模板。此方法在高速缓存中查找模板,或通过调用get_source()加载模板。子类不应覆盖此方法,因为加载器在其他加载器的集合(例如PrefixLoaderChoiceLoader)上不会调用此方法,而是直接调用get_source

这里有一个 Jinja2 提供的内置加载器的列表:

class jinja2.FileSystemLoader(searchpath, encoding='utf-8', followlinks=False)

从文件系统加载模板。这个加载器可以在文件系统上的文件夹中找到模板,并且是加载它们的首选方式。

加载器将模板的路径作为字符串,或者如果需要多个位置,则它们的列表将按给定顺序查找:

>>> loader = FileSystemLoader('/path/to/templates')
>>> loader = FileSystemLoader(['/path/to/templates', '/other/path'])

默认情况下,模板编码为'utf-8',可以通过将encoding参数设置为其他值来更改。

To follow symbolic links, set the followlinks parameter to True:

>>> loader = FileSystemLoader('/path/to/templates', followlinks=True)

Changed in version 2.8+: The followlinks parameter was added.

class jinja2.PackageLoader(package_name, package_path='templates', encoding='utf-8')

Implementation 它使用python包的名称和该包中模板的路径构造:

loader = PackageLoader('mypackage', 'views')

如果未指定软件包路径,则假设为'templates'

默认情况下,模板编码为'utf-8',可以通过将encoding参数设置为其他值来更改。由于egg的性质,只有当从文件系统加载包而不是zip文件时,才可以重新加载模板。

class jinja2.DictLoader(mapping)

Raised if a template does not exist. 它传递了绑定到模板名称的unicode字符串的dict。这个加载器对于单元测试是有用的:

>>> loader = DictLoader({'index.html': 'source here'})

因为自动重新加载很少有用,所以默认情况下禁用。

class jinja2.FunctionLoader(load_func)

一个块渲染函数的字典。 该函数接收模板的名称,并返回一个unicode字符串与模板源,一个tuple形式(源, 文件名, uptodatefunc)

>>> def load_template(name):
...     if name == 'index.html':
...         return '...'
...
>>> loader = FunctionLoader(load_template)

uptodatefunc是在启用autoreload时调用的函数,如果模板仍然是最新的,则必须返回True有关更多详细信息,请查看具有相同返回值的BaseLoader.get_source()

class jinja2.PrefixLoader(mapping, delimiter='/')

一个加载器,它通过加载器的dict,其中每个加载器绑定到一个前缀。前缀通过每个默认值的斜杠与模板分隔,可以通过将delimiter参数设置为其他值来更改前缀:

loader = PrefixLoader({
    'app1':     PackageLoader('mypackage.app1'),
    'app2':     PackageLoader('mypackage.app2')
})

By loading 'app1/index.html' the file from the app1 package is loaded, by loading 'app2/index.html' the file from the second.

class jinja2.ChoiceLoader(loaders)

loader 如果一个加载器找不到模板,则尝试下一个加载器。

>>> loader = ChoiceLoader([
...     FileSystemLoader('/path/to/user/templates'),
...     FileSystemLoader('/path/to/system/templates')
... ])

如果要允许用户从不同的位置覆盖内置模板,这将非常有用。

class jinja2.ModuleLoader(path)

此加载程序从预编译的模板加载模板。

用法示例:

>>> loader = ChoiceLoader([
...     ModuleLoader('/path/to/compiled/templates'),
...     FileSystemLoader('/path/to/templates')
... ])

Templates can be precompiled with Environment.compile_templates().

字节码缓存

Jinja 2.1 和更高的版本支持外部字节码缓存。 字节码缓存使得在首次使用时把生成的字节码 存储到文件系统或其它位置来避免处理模板。

这在当你有一个在首个应用初始化的 web 应用, Jinja 一次性编译大量模板拖慢应用时尤其 有用。

要使用字节码缓存,把它实例化并传给 Environment

class jinja2.BytecodeCache

要实现自己的字节码缓存,您必须对该类进行子类化,并覆盖load_bytecode()dump_bytecode()这两种方法都通过Bucket

一个非常基本的字节码缓存,用于在文件系统上保存字节码:

from os import path

class MyCache(BytecodeCache):

    def __init__(self, directory):
        self.directory = directory

    def load_bytecode(self, bucket):
        filename = path.join(self.directory, bucket.key)
        if path.exists(filename):
            with open(filename, 'rb') as f:
                bucket.load_bytecode(f)

    def dump_bytecode(self, bucket):
        filename = path.join(self.directory, bucket.key)
        with open(filename, 'wb') as f:
            bucket.write_bytecode(f)

基于文件系统的字节码缓存的更高级版本是Jinja2的一部分。

clear()

清除缓存。Jinja2不使用此方法,但应实现该方法以允许应用程序清除特定环境使用的字节码缓存。

dump_bytecode(bucket)

子类必须重写此方法以将字节码从存储桶写回缓存。如果它不能这样做,它不能默默失败,但引发异常。

load_bytecode(bucket)

子类必须覆盖此方法以将字节码加载到存储桶中。如果他们不能在存储桶的缓存中找到代码,它不能做任何事情。

class jinja2.bccache.Bucket(environment, key, checksum)

存储桶用于存储一个模板的字节码。它由字节码缓存创建和初始化,并传递到加载函数。

存储桶从分配的缓存中获取内部校验和,并使用此自动拒绝过期的缓存材料。各个字节码缓存子类不必关心缓存无效。

environment

创建存储桶的Environment

key

此存储桶的唯一缓存键

code

如果已加载,则为字节码,否则为 None

bytecode_from_string(string)

从字符串加载字节码。

bytecode_to_string()

将字节码作为字符串返回。

load_bytecode(f)

从文件或文件(如对象)加载字节码。

reset()

重置存储桶(卸载字节码)。

write_bytecode(f)

将字节码转储到像传递的对象的文件或文件中。

内建的字节码缓存:

class jinja2.FileSystemBytecodeCache(directory=None, pattern='__jinja2_%s.cache')

字节码缓存,用于在文件系统上存储字节码。它接受两个参数:缓存项目存储的目录和用于构建文件名的模式字符串。

如果未指定目录,则选择默认高速缓存目录。 This loader loads templates from precompiled templates.

该模式可用于使多个单独的缓存在同一目录上操作。默认模式为'__jinja2_%s.cache'%s替换为缓存键。

>>> bcc = FileSystemBytecodeCache('/tmp/jinja_cache', '%s.cache')

Quick search

class jinja2.MemcachedBytecodeCache(client, prefix='jinja2/bytecode/', timeout=None, ignore_memcache_errors=True)

这个类实现了一个字节码缓存,它使用内存缓存缓存来存储信息。 This bytecode cache supports clearing of the cache using the clear method.

与此类兼容的库:

(不幸的是django缓存接口不兼容,因为它不支持存储二进制数据,只有unicode。但是,您可以将底层缓存客户端传递到可用作django.core.cache.cache._client的字节码缓存。

客户端传递给构造函数的最小接口是:

class MinimalClientInterface
set(key, value[, timeout])

将字节码存储在缓存中。是一个字符串,超时键的超时。如果未提供超时,则应假设为缺省超时或不超时,如果提供超时,则它是一个带有缓存项目应存在的秒数的整数。

get(key)

返回高速缓存密钥的值。如果项目不存在于高速缓存中,则返回值必须为

构造函数的其他参数是在实际缓存键之前添加的所有键的前缀,以及缓存系统中字节码的超时。我们建议高(或没有)超时。

此字节码缓存不支持清除缓存中已使用的项目。清除方法是无操作功能。

New in version 2.7: Added support for ignoring memcache errors through the ignore_memcache_errors parameter.

实用工具

这些辅助函数和类在你向 Jinja2 环境中添加自定义过滤器或函数时很有用。

jinja2.environmentfilter(f)

用于标记依赖于环境的过滤器的装饰器。当前Environment作为第一个参数传递到过滤器。

jinja2.contextfilter(f)

用于标记上下文相关过滤器的装饰器。当前Context将作为第一个参数传递。

jinja2.evalcontextfilter(f)

用于标记eval-上下文相关过滤器的装饰器。eval上下文对象作为第一个参数传递。有关eval上下文的更多信息,请参见Evaluation Context

版本2.4中的新功能。

jinja2.environmentfunction(f)

这个装饰器可以用于将函数或方法标记为环境可调用的。这个装饰器与contextfunction()装饰器完全一样,只是第一个参数是活动的Environment而不是上下文。

jinja2.contextfunction(f)

这个装饰器可以用来标记函数或方法上下文可调用。当从模板调用时,上下文可调用传递的活动Context作为第一个参数。如果函数想要访问上下文对象上提供的上下文或函数,这将非常有用。例如,返回模板变量的排序列表的函数,当前模板导出可能如下所示:

@contextfunction
def get_exported_names(context):
    return sorted(context.exported_vars)
jinja2.evalcontextfunction(f)

这个装饰器可以用来将函数或方法标记为eval上下文可调用。这类似于contextfunction(),但是不传递上下文,而是传递评估上下文对象。有关eval上下文的更多信息,请参见Evaluation Context

版本2.4中的新功能。

jinja2.escape(s)

把字符串 s&<>'" 转换为 HTML 安 全的序列。 如果你需要在 HTML 中显示可能包含这些字符的文本,可以使用它。 这 个函数不会转义对象。

返回值是一个 Markup 字符串。

jinja2.clear_caches()

Jinja2保留环境和词法分析器的内部缓存。这些被使用,所以Jinja2不必一直重新创建环境和词法分析器。通常你不必关心,但如果你是内存消耗,你可能想要清理缓存。

jinja2.is_undefined(obj)

检查传递的对象是否未定义。这只是对Undefined执行实例检查,但看起来更好。这可以用于要对未定义的变量做出反应的自定义过滤器或测试。例如,自定义默认过滤器可能如下所示:

def default(var, default=''):
    if is_undefined(var):
        return default
    return var
class jinja2.Markup([string])

将字符串标记为可以安全地包含在HTML / XML输出中,而无需转义。这实现了几个框架和Web应用程序使用的__ html __接口。Markupunicode的直接子类,提供unicode的所有方法,只是它转义传递的参数,并始终返回t5>。

escape函数返回标记对象,因此不会发生双重转义。

Markup类的构造函数可以用于三个不同的事情:当传递一个unicode对象时,假定它是安全的,当传递一个具有HTML表示的对象(有一个__ html __ t3 >方法),否则传递的对象将转换为unicode字符串,然后假定为安全的:

>>> Markup("Hello <em>World</em>!")
Markup(u'Hello <em>World</em>!')
>>> class Foo(object):
...  def __html__(self):
...   return '<a href="#">foo</a>'
...
>>> Markup(Foo())
Markup(u'<a href="#">foo</a>')

如果想要传递的对象始终被视为不安全,您可以使用escape() classmethod创建Markup对象:

>>> Markup.escape("Hello <em>World</em>!")
Markup(u'Hello &lt;em&gt;World&lt;/em&gt;!')

标记字符串上的操作是标记感知的,这意味着所有参数都通过escape()函数传递:

>>> em = Markup("<em>%s</em>")
>>> em % "foo & bar"
Markup(u'<em>foo &amp; bar</em>')
>>> strong = Markup("<strong>%(text)s</strong>")
>>> strong % {'text': '<blink>hacker here</blink>'}
Markup(u'<strong>&lt;blink&gt;hacker here&lt;/blink&gt;</strong>')
>>> Markup("<em>Hello</em> ") + "<foo>"
Markup(u'<em>Hello</em> &lt;foo&gt;')
classmethod escape(s)

逃离字符串。escape()工作,区别在于Markup的子类会返回正确的子类。

striptags()

将标记取消转义为text_type字符串并剥离所有标记。这也解决了已知的HTML4和XHTML实体。空格被标准化为一:

>>> Markup("Main &raquo;  <em>About</em>").striptags()
u'Main \xbb About'
unescape()

将标记再次解析为text_type字符串。这也解决了已知的HTML4和XHTML实体:

>>> Markup("Main &raquo; <em>About</em>").unescape()
u'Main \xbb <em>About</em>'

注意

Jinja2 的 Markup 类至少与 Pylons 和 Genshi 兼容。 预计不久更多模板 引擎和框架会采用 __html__ 的概念。

异常

exception jinja2.TemplateError(message=None)

Baseclass for all template errors.

exception jinja2.UndefinedError(message=None)

在模板尝试对Undefined进行操作时引发。

exception jinja2.TemplateNotFound(name, message=None)

在模板不存在时引发。

exception jinja2.TemplatesNotFound(names=(), message=None)

TemplateNotFound,但如果选择多个模板,则会引发。这是TemplateNotFound异常的子类,所以只捕获基本异常将捕获两者。

版本2.2中的新功能。

exception jinja2.TemplateSyntaxError(message, lineno, name=None, filename=None)

提示告诉用户模板有问题。

message

错误信息的 utf-8 字节串。

lineno

发生错误的行号。

name

模板的加载名的 unicode 字符串。

filename

加载的模板的文件名字节串,以文件系统的编码(多是 utf-8 , Windows 是 mbcs )。

文件名和错误消息是字节串而不是 unicode 字符串的原因是,在 Python 2.x 中,不对异常和回溯使用 unicode ,编译器同样。 这会在 Python 3 改变。

exception jinja2.TemplateAssertionError(message, lineno, name=None, filename=None)

像模板语法错误一样,但是涵盖了模板中的某些东西在编译时引起错误的情况,这些错误不一定是由语法错误引起的。但它是TemplateSyntaxError的直接子类,并具有相同的属性。

自定义过滤器

自定义过滤器只是常规的 Python 函数,过滤器左边作为第一个参数,其余的参数作 为额外的参数或关键字参数传递到过滤器。

例如在过滤器 {% templatetag openvariable %} 42|myfilter(23) {% templatetag closevariable %} 中,函数被以 myfilter(42, 23) 调 用。 这里给出一个简单的过滤器示例,可以应用到 datetime 对象来格式化它们:

def datetimeformat(value, format='%H:%M / %d-%m-%Y'):
    return value.strftime(format)

你可以更新环境上的 filters 字典来把它注册到模板环境上:

environment.filters['datetimeformat'] = datetimeformat

在模板中使用如下:

written on: {{ article.pub_date|datetimeformat }}
publication date: {{ article.pub_date|datetimeformat('%d-%m-%Y') }}

也可以传给过滤器当前模板上下文或环境。 当过滤器要返回一个未定义值或检查当前的 autoescape 设置时很有用。 为此,有三个装饰器: environmentfilter()contextfilter()evalcontextfilter()

这里是一个小例子,过滤器把一个文本在 HTML 中换行或分段,并标记返回值为安全 的 HTML 字符串,因为自动转义是启用的:

import re
from jinja2 import evalcontextfilter, Markup, escape

_paragraph_re = re.compile(r'(?:\r\n|\r|\n){2,}')

@evalcontextfilter
def nl2br(eval_ctx, value):
    result = u'\n\n'.join(u'<p>%s</p>' % p.replace('\n', Markup('<br>\n'))
                          for p in _paragraph_re.split(escape(value)))
    if eval_ctx.autoescape:
        result = Markup(result)
    return result

上下文过滤器工作方式相同,只是第一个参数是当前活动的 Context 而 不是环境。

评估上下文

求值上下文(缩写为 eval context 或 eval ctx )是 Jinja 2.4 中引入的新对象, 并可以在运行时激活/停用已编译的特性。

当前它只用于启用和禁用自动转义,但也可以用于扩展。

在之前的 Jinja 版本中,过滤器和函数被标记为环境可调用的来从环境中检查自动 转义的状态。 在新版本中鼓励通过求值上下文来检查这个设定。

之前的版本:

@environmentfilter
def filter(env, value):
    result = do_something(value)
    if env.autoescape:
        result = Markup(result)
    return result

在新版本中,你可以用 contextfilter() 从实际的上下文中访问求值上下 文,或用 evalcontextfilter() 直接把求值上下文传递给函数:

@contextfilter
def filter(context, value):
    result = do_something(value)
    if context.eval_ctx.autoescape:
        result = Markup(result)
    return result

@evalcontextfilter
def filter(eval_ctx, value):
    result = do_something(value)
    if eval_ctx.autoescape:
        result = Markup(result)
    return result

求值上下文一定不能在运行时修改。 修改只能在扩展中的 用 nodes.EvalContextModifiernodes.ScopedEvalContextModifier 发生,而不是通过求值上下文对 象本身。

class jinja2.nodes.EvalContext(environment, template_name=None)

保存评估时间信息。自定义属性可以在扩展中附加到它。

autoescape

TrueFalse 取决于自动转义是否激活。

volatile

如果编译器不能在编译期求出某些表达式的值,为 True 在运行时应该 始终为 False

自定义测试

测试像过滤器一样工作,只是测试不能访问环境或上下文,并且它们不能链式使用。 测试的返回值应该是 TrueFalse 测试的用途是让模板设计者运行类型和 一致性检查。

这里是一个简单的测试,检验一个变量是否是素数:

import math

def is_prime(n):
    if n == 2:
        return True
    for i in xrange(2, int(math.ceil(math.sqrt(n))) + 1):
        if n % i == 0:
            return False
    return True

你可以通过更新环境上的 tests 字典来注册它:

environment.tests['prime'] = is_prime

模板设计者可以在之后这样使用测试:

{% if 42 is prime %}
    42 is a prime number
{% else %}
    42 is not a prime number
{% endif %}

全局命名空间

Environment.globals 字典中的变量是特殊的,它们对导入的模板也是可用的, 即使它们不通过上下文导入。 这是你可以放置始终可访问的变量和函数的地方。 此外, Template.globals 是那些对特定模板可用的变量,即对所有的 render() 调用可用。

低层 API

低层 API 暴露的功能对理解一些实现细节、调试目的或高级 扩展 技巧是有用的。 除非你准确地了解你在做什么,否则 不推荐使用这些 API 。

Environment.lex(source, name=None, filename=None)

Lex给定源代码并返回一个生成器,它以(lineno, token_type, 值)的形式产生令牌为元组>。这对于extension development和调试模板很有用。

这不执行预处理。如果想要应用扩展的预处理,则必须通过preprocess()方法过滤源。

Environment.parse(source, name=None, filename=None)

解析源代码并返回抽象语法树。编译器使用这个节点树将模板转换为可执行的源或字节码。这对于调试或从模板中提取信息很有用。

如果您developing Jinja2 extensions,这将为您提供生成的节点树的良好概述。

Environment.preprocess(source, name=None, filename=None)

预处理具有所有扩展名的源。这对于所有解析和编译方法自动调用,但用于lex(),因为通常只需要实际的源标记化。

Template.new_context(vars=None, shared=False, locals=None)

为此模板创建新的Context提供的变量将被传递给模板。默认情况下,全局变量被添加到上下文中。如果shared设置为True,则将数据作为上下文传递,而不添加全局变量。

locals可以是内部使用的局部变量的dict。

Template.root_render_func(context)

这是低层的渲染函数。 它接受一个必须由相同模板或兼容的模板的 new_context() 创建的 Context 这个渲染函数由编译器从 模板代码产生,并返回一个生产 unicode 字符串的生成器。

如果模板代码中发生了异常,模板引擎不会重写异常而是直接传递原始的异常。 事实上,这个函数只在 render() / generate() / stream() 的调用里被调用。

Template.blocks

块的dict表示函数。 其中的每个函数与 root_render_func() 的工作 相同,并且有相同的限制。

Template.is_up_to_date

如果有可用的新版本模板,这个属性是 False ,否则是 True

注意

低级API比较脆弱。 未来的 Jinja2 的版本将不会试图以不向后兼容的方式修改它, 而是在 Jinja2 核心的修改中表现出来。 比如如果 Jinja2 在之后的版本中引入一 个新的 AST 节点,它会由 parse() 返回。

Meta API

版本2.2中的新功能。

元 API 返回一些关于抽象语法树的信息,这些信息能帮助应用实现更多的高级模板概 念。 所有的元 API 函数操作一个 Environment.parse() 方法返回的抽象语法 树。

jinja2.meta.find_undeclared_variables(ast)

返回在运行时将从上下文中查找的AST中的所有变量的集合。因为在编译时,根据执行在运行时所采用的路径不知道使用哪些变量,所有变量都返回。

>>> from jinja2 import Environment, meta
>>> env = Environment()
>>> ast = env.parse('{% set foo = 42 %}{{ bar + foo }}')
>>> meta.find_undeclared_variables(ast) == set(['bar'])
True

实施

在内部,代码生成器用于查找未声明的变量。这是很好知道,因为代码生成器可能会在编译期间引发TemplateAssertionError,事实上,该函数目前可以提出该异常。

jinja2.meta.find_referenced_templates(ast)

从AST中查找所有引用的模板。这将返回一个迭代器在所有硬编码模板扩展,包含和导入。如果使用动态继承或包含,将产生

>>> from jinja2 import Environment, meta
>>> env = Environment()
>>> ast = env.parse('{% extends "layout.html" %}{% include helper %}')
>>> list(meta.find_referenced_templates(ast))
['layout.html', None]

此函数对依赖关系跟踪很有用。例如,如果您想在布局模板更改后重新构建网站的部分。