介绍
Jinja是基于Python的模板引擎,功能比较相似于于PHP的smarty,J2ee的Freemarker和velocity。
运行需求
Jinja2须要Python2.4以上的版本。
安装
按照Jinja有多种方式,你能够根据须要选择不一样的按照方式。
使用easy_install安装
使用easy_install 或pip:
#sudo easy_install Jinja2
#sudo pip install Jinja2
这两个工具能够自动从网站上下载Jinja,并安装到python目录的site-packages目录中。
从tar包安装
# 下载Jinja的安装包
# 解压缩
# sudo python setup.py install
基本API用法
用Jinja建立模板最简单的方式是经过 Template. 但在实际应用中并不推荐此用法:
<pre>
>>> from Jinja2 import Template
>>> template = Template('Hello ` name `!')
>>> template.render(name='World')
u'Hello World!'
</pre>
这个例子使用字符串做为模板内容建立了一个Template实例,而后用"name='World'"做为参数调用"render方法,将内容中 的'name'替换为"World",最终返回渲染过的字符串--"u'Hello World!'"。
API
Environment
Environment是Jinja2中的一个核心类,它的实例用来保存配置、全局对象,以及从本地文件系统或其它位置加载模板。
多数应用会在初始化时建立Environment实例,而后用它来加载模板。固然,若是系统有必要使用不一样的配置,也能够建立多个 Environment实例一块儿使用。
配置Jinja2为你的应用加载模板的最简单的方式能够像下面这样:
from Jinja2 import Environment, PackageLoader
env = Environment(loader=<script type="text/JavaScript" src="http://www.javaeye.com/javascripts/tinymce/themes/advanced/langs/zh.js"></script><script type="text/javascript" src="http://www.javaeye.com/javascripts/tinymce/plugins/javaeye/langs/zh.js"></script>PackageLoader('yourapplication', 'templates'))
上述代码使用缺省配置建立了一个Environment实例,并指定PackageLoader做为模板加载器。PackageLoader能够 从你的python应用程序的包中读取并加载模板。在以后的文档中会逐一介绍Jinja2的加载器。
建立了Environment实例,咱们就能够加载模板了:
template = env.get_template('mytemplate.html')
以后就能够跟上文中的例子同样用render方法来渲染模板了。
print template.render(the='variables', Go='here')
高级API
Environment类:
class Environment(block_start_string='{%', block_end_string='%}', variable_start_string='{{', vari-
able_end_string='}}', comment_start_string='{#', comment_end_string='#}',
line_statement_preix=None, trim_blocks=False, extensions=(), optimized=True,
undefined=<class 'Jinja2.runtime.Undefined'>, finalize=None, autoescape=False,
loader=None)
Environment是Jinja2的核心组件,它包含了重要的共享变量,例如:配置,过滤器,测试器,全局变量等等。Environment 的实例若是没有被共享或者没有加载过模板则能够进行修改,若是在加载过模板以后修改Environment实例会遇到不可知的结果。
参数介绍:
loader 模板加载器.
block_start_string 块开始标记符,缺省是 '{%'.
block_end_string 块结束标记符,缺省是 '%}'.
variable_start_string 变量开始标记符,缺省是 '{{'.
variable_start_string 变量结束标记符,缺省是 '{{'.
comment_start_string 注释开始标记符,缺省是 '{#'.
comment_end_string 注释结束标记符,缺省是 '#}'.
经过修改上面几个标记符参数,可让咱们的模板变成另一种风格,好比
env = Environment(
block_start_string="<#", block_end_string="#>,
variable_start_string="${", variable_start_string="}",
comment_start_string="<#--", comment_end_string="--#>", ...)
这样,咱们的模板能够设计为下面的样子:
<# block title #> Index <# endblock #>
${name}
<#-- this is comment --#>
怎么样,是否是有点像freemarker的风格?可是咱们不推荐这样作,不然就没法使用Jinja的编辑器来编辑模板了。
auto_reload
若是设为True,Jinja会在使用Template时检查模板文件的状态,若是模板有修改, 则从新加载模板。若是对性能要求较高,能够将此值设为False。
autoescape XML/HTML自动转义,缺省为false. 就是在渲染模板时自动把变量中的<>&等字符转换为<>&。
cache_size
缓存大小,缺省为50,即若是加载超过50个模板,那么则保留最近使用过多50个模板,其它会被删除。若是换成大小设为0,那么全部模板都会在使用时被重 编译。若是不但愿清除缓存,能够将此值设为-1.
undefined Undefined或者其子类,用来表现模板中未定义的值
使用过freemarker的朋友应该知道,在freemarker中模板中使用值为null的变量时会看到一个“很黄很暴力”的一堆错误栈信息。有些人 对freemarker的这种处理方式不觉得然,由于这样还须要对变量值加入判断,处理起来比较繁琐。而另外一个比较有名气的模板引擎Velocity则会 忽略空值,例如在Velocity中打印值为null的变量将会获得一个空字符。
Jinja经过设置不一样的undefined参数来获得相似Freemarker或者Velocity的处理方式。
line_statement_prefix 指定行级语句的前缀.
extensions Jinja的扩展的列表,能够为导入到路径字符串或者表达式类
Template类
Template类是Jinja的另外一个重要的组件,它能够被看做是一个编译过的模板文件,被用来产生目标文本.
Template类的构建器参数和Environment类基本相同, 区别是,建立Template实例须要一个模板文本参数,另外它不须要loader参数。
Template实例是一个不可变对象,即你不能修改Template实例的属性。
通常状况下,咱们会使用Environment实例来建立Template,但也能够直接使用Template构建器来建立。若是要用构建器来创 建Template实例,那么Jinja会根据构建器参数自动为此Template建立/指派一个内部Environment实例,凡是使用相同构建器参 数(不包括模板文本串参数)建立的Template实例都会共享同一个内部Environment实例。
方法:
<pre>render(*args, **kwargs)</pre>
此方法接受与“dict”相同的构建器参数:一个dict,dict的子类,或者一些关键字参数。下面两种调用方式是等价的:
template.render(knights='that say nih')
template.render({'knights': 'that say nih'})
<pre>generate(*args, **kwargs)</pre>
此方法会一段一段的渲染模板,而不是一次性的将整个模板渲染成目标文本。这对产生很是大的模板时很是有用。调用此方法会返回一个产生器 (generator),它能够....
<pre>stream(*args, **kwargs)</pre>
与generate功能相似,只不过此方法返回一个TemplateStream module
此方法用来在模板运行时导入, 也能够用来在python代码中访问导出的模板变量.
>>> t = Template('{% macro foo() %}42{% endmacro %}23')
>>> unicode(t.module)
u'23'
>>> t.module.foo()
u'42'.
Undened Types 未定义类型
Undened及其子类类被用来做为未定义类型。Environment的构建器能够指定undefined参数,它能够是undefined types中的任意一个,或者是Undefined的子类。当模板引擎没法找到一个名称或者一个属性时,使用的Undefined会决定哪些操做能够正常 进行,哪些不能够。
'''class Undefined(hint=None, obj=None, name=None)'''
缺省undefined类型。此未定义类型能够打印或者做为sequence迭代。可是不能作其它操做,不然会抛出UndefinedError
<pre>
foo = Undefined(name='foo')
>>> str(foo)
''
>>> not foo
True
>>> foo + 42
Traceback (most recent call last):
...
Jinja2.exceptions.UndefinedError: 'foo' is undefined
</pre>
'''class DebugUndefined(hint=None, obj=None, name=None)'''
<pre>
>>> foo = DebugUndefined(name='foo')
>>> str(foo)
'` foo `'
>>> not foo
True
>>> foo + 42
Traceback (most recent call last):
...
Jinja2.exceptions.UndefinedError: 'foo' is undefined
</pre>
'''class StrictUndefined(hint=None, obj=None, name=None)'''
<pre>
>>> 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
</pre>
Loaders 加载器
加载器负责从某些位置(好比本地文件系统)中加载模板,并维护在内存中的被编译过的模块。
文件系统加载器,它能够从本地文件系统中查找并加载模板:
class FileSystemLoader(searchpath, encoding='utf-8', cache_size=50, auto_reload=True)
第一个参数searchpath是查找路径,它能够是一个路径字符串,也能够是保护多个路径的sequence。
>>> loader = FileSystemLoader('/path/to/templates')
>>> loader = FileSystemLoader(['/path/to/templates', '/other/path'])
包加载器。它能够从python包中加载模板:
class PackageLoader(package_name, package_path='templates', encoding='utf-8', cache_size=50, auto_reload=True)
>>> loader = PackageLoader('mypackage', 'views')
字典加载器。在mapping参数中明确指定模板文件名的路径。它用来作单元测试比较有用:
class DictLoader(mapping, cache_size=50, auto_reload=False)
>>> loader = DictLoader({'index.html': 'source here'})
函数加载器。让指定的函数来返回模板文件的路径。
class FunctionLoader(load_func, cache_size=50, auto_reload=True)
>>> def load_template(name):
... if name == 'index.html'
... return '...'
...
>>> loader = FunctionLoader(load_template)
前缀加载。若是你的工程中包含不少应用,那么多应用之间模板名称就可能存在命名冲突的问题。使用前缀加载器能够有效的解决不一样应用之间模板命名冲 突问题。
class PrefixLoader(mapping, delimiter='/', cache_size=50, auto_reload=True)
>>> loader = PrefixLoader({
... 'app1': PackageLoader('mypackage.app1'),
... 'app2': PackageLoader('mypackage.app2')
... })
如此,若是要使用app1中的模板,能够get_template('app1/xxx.html'), 使用app2的模板,可使用get_template('app2/xxx.html')。delimiter字符决定前缀和模板名称之间的分隔符,默 认为'/'。
选择加载器,与PrefixLoader相似,能够组合多个加载器。当它在一个子加载器中查找不到模板时,它会在下一个子加载器中继续查找。若是 你要用一个不一样的位置覆盖内建模板时很是有用
class ChoiceLoader(loaders, cache_size=50, auto_reload=True)
>>> loader = ChoiceLoader([
... FileSystemLoader('/path/to/user/templates'),
... PackageLoader('myapplication')
全部加载都继承自BaseLoader,若是你要实现一个自定义加载能够,能够写一个BaseLoader的子类,并覆盖get_source方 法。
class BaseLoader(cache_size=50, auto_reload=True)
一个简单的例子
from Jinja2 import BaseLoader, TemplateNotFound
from os.path import join, exists, getmtime
class MyLoader(BaseLoader):
def __init__(self, path, cache_size=50, auto_reload=True):
BaseLoader.__init__(self, cache_size, auto_reload)
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)
load(environment, name, globals=None)
加载一个模板。此方法会在缓存中查找模板,若是缓存中不存在则调用get_source获得模板的内容,缓存后返回结果。
注意,BaseLoader已经实现了load方法,它对模板的缓存进行了处理。若是你不须要本身维护缓存,则没必要重写此方法。
Utilites
用来帮助你添加自定义过滤器或者函数到Jinja中
environmentfilter(f)
contextfilter(f)
environmentfunction(f)
contextfunction(f)
escape(s)
class Markup()
异常
javascript
类名 | 描述 |
class TemplateError() | 全部模板异常的基类 |
class UndefinedError() | 操做一个未定义对象时 |
class TemplateNotFound(name) | 模板未找到 |
class TemplateSyntaxError(message, lineno, name) | 模板语法错误 |
模板设计文档
概述
一个模板其实就是一个普通的文本文件。它能够被设计为任何文本格式(HTML,XML,CSV等等)。它也不须要肯定的扩展名,不过通常咱们都会 用'.html'或'.xml'
模板中包含变量,表达式,标签,变量和表达式会在模板渲染时被用值来替换,标签控制模板的逻辑。Jinja的语法主要参考自Django和 python。
下面是一个简单的模板,它包含的了几个模板中的基本元素,在以后的文档中会对这些元素作详细说明。
<pre>
<!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>
</pre>
这个模板中包含了两种标记符"{% ... %}"与"` `.``.` `", 前者用来执行一个循环或者一个赋值语句,后者用来打印一个变量。
变量
你能够传递python的变量给模板,用来替换模板中的标记。这些变量能够是任何Python对象。在模板中能够直接操做传入的变量对象,也能够 访问这些变量的属性。
访问变量属性有两种方式,一种是用"obj.attr"的方式,另外一种是相似字典的方式:"obj['attr']".
<pre>
` foo`.`bar `
{{ foo['bar'] }}
</pre>
注意,上面的'` `.``.` `是Jinja的用来打印变量标记。若是要在其它标签中访问变量,则不能在变量名旁边加花括号。
过滤器(filters)
变量能够在模板中被过滤器修改. 使用过滤器的方式比较相似管道(pipe)操做。如:
<pre> '{{ name|striptags|title }}'</pre>
这个例子的意思是:将name变量用striptags消除变量值中的tag(用<>括起来的内容),再用title过滤器将首字符 大写。
过滤器也能够接受参数,用起来比较像调用函数
<pre> '{{ list|join(', ') }}'</pre>
内建过滤器介绍参见内建过滤器一节。
检查器(Tests)
检查器用来在Jinja的if块里面检查一个变量是否符合某种条件。它的用法是 varname is atest, 例如检查一个变量是否存在
{% if name is defined %}
这里, defined就是一个检查器。
检查器跟过滤器同样,也能够有参数,若是检查器只有一个参数,能够不写括号,直接用一个空格将检查器名和参数隔开,以下例中,两行代码的做用是一 样的:
{% if loop.index is divisibleby 3 %}
{% if loop.index is divisibleby(3) %}
在后面的内建检查器列表一节中会介绍各个内建检查器
注释
Jinja中能够加入注释,如:
{# note: disabled template because we no longer user this
{% for user in users %}
...
{% endfor %}
#}
这些注释内容不会出如今模板产生的文本中。
模板继承
模板继承是Jinja中一个很是有用的功能。这个功能容许你建立一个包含有全部公共元素的页面基本骨架,在子模板中能够重用这些公用的元素。
使用模板继承其实很简单,下面咱们开始用一个例子来介绍模板继承的用法。
基础模板
咱们首先写一个名为"base.html"的模板,它包含下面的内容:
<pre>
<!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>
</pre>
在这个模板中有不少'block', 这些block中间的内容,咱们将会在子模板中用其它内容替换。
子模板
咱们再写一个名为"child.html"的模板,内容以下:
<pre>
{% 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 awsome homepage.
</p>
{% endblock %}
</pre>
:在这个模板的第一行,咱们用{% extends "base.html" %}标明,这个模板将继承base.html.
在随后的内容中包含了不少跟base.html中相同的block,如title,content,这些block中的内容将会替换 base.html的内容后输出.
:extends后面的模板名称的写法依赖于此模板使用的模板加载器, 好比若是要使用FileSystemLoader,你能够在模板文件名中加入文件的文件夹名,如:
<pre>
{% extends "layout/default.html" %}
</pre>
在base.html中,咱们定义了block “footer”,这个block在子模板中没有被重定义,那么Jinja会直接使用父模板中的内容输出。
另外要注意,在同一个模板中不能定义名称相同的block。
若是你要在模板中屡次打印同一个block,能够用用self变量加上block的名字:
<pre>
<title>{% block title %}{% endblock %}</title>
<h1>{{ self.title() }}</h1>
{% block body %}{% endblock %}
</pre>
和Python不一样的地方是,Jinja不支持多继承。
super block
若是要在子模板中重写父模板的block中打印被重写的block的内容,能够调用super关键字。
<pre>
{% block sidebar %}
<h3>Table Of Contents</h3>
...
{{ super() }}
{% endblock %}
<pre>
HTML转义
:咱们传递给模板的变量中可能会有一些html标记符,这些标记符也许会影响咱们页面的正常显示,并且会给咱们的站点带来跨站脚本***的隐患。
Jinja提供了两种方式-自动或者手工来对变量值进行html转义,即把'<'转换为'<','>'转换为 '>','&'转换为'&'
经过给Environment或Template的构建器传递autoescape参数,能够设置自动转义与否。
手动转义
这种方式须要咱们使用过滤器转换咱们须要转义的变量
'{{ user.username|e }}'. 这里'e'就是转义过滤器
自动转义
这种方式会在打印变量时自动进行转义。除非使用'safe'过滤器标明不须要转义:
<pre>
'{{ user.username|safe }}'.
</pre>
结构控制标记
Jinja中的控制标记包括:条件判断标记(if/elif/else),循环控制(for-loop),另外还有macro(宏)和上文中提到 的block。
for
循环打印一个序列,例如:
<pre>
<h1>Members</h1>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
</pre>
在循环内部,你能够访问一些特殊的变量php
Variable | Description |
loop.index | 当 前迭代的索引,从1开始算 |
loop.index0 | 当前迭代的索引,从0开始算 |
loop.revindex | 相 对于序列末尾的索引,从1开始算 |
loop.revindex0 | 相对于序列末尾的索引,从0开始算 |
loop.first | 相 当于 loop.index == 1. |
loop.last | 至关于 loop.index == len(seq) - 1 |
loop.length | 序列的长度. |
loop.cycle | 是 一个帮助性质的函数,能够接受两个字符串参数,若是当前循环索引是偶数,则显示第一个字符串,是奇数则显示第二个字符串。它常被在表格中用来用不一样的背景 色区分相邻的行。 |
<pre>
{% for row in rows %}
<li class="{{ loop.cycle('odd', 'even') }}">` row `</li>
{% endfor %}
</pre>
须要注意的是,Jinja的循环不支持break和continue标记。你能够对须要迭代的sequence使用过滤器来达到与break和 continue相同的目的。
下面的例子中,若是user.hidden属性为true的则continue
<pre>
{% for user in users if not user.hidden %}
<li>{{ user.username|e }}</li>
{% endfor %}
</pre>
Jinja的for语句有一个和python相同的用法,那就是“else':当无循环时显示else中的内容,以下例:
<pre>
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% else %}
<li><em>no users found</em></li>
{% endif %}
</ul>
</pre>
if
if语句用来在Jinja中作比较判断,比较常见的用法是判断一个变量是否已定义,是否非空,是否为true
<pre>
{% if users %}
<ul>
{% for user in users %}
<li>{{ user.username|e }}</li>
{% endfor %}
</ul>
{% endif %}
</pre>
和python同样,也可使用elif和else
<pre>
{% if kenny.sick %}
Kenny is sick.
{% elif kenny.dead %}
You killed Kenny! You bastard!!!
{% else %}
Kenny looks okay --- so far
{% endif %}
</pre>
if语句也能够被用来作内联表达式或者for语句过滤器。
宏(Macro)
宏的做用和函数比较相似。用来把一部分经常使用的代码封装起来,避免重复性的工做。
宏能够定义在一个帮助性质的模板中,用imported的方式被其它模板引用;也能够在模板中定义并直接使用。这两种方式有个显著的不一样:在模板 中定义的宏能够访问传给模板的上下文变量;在其它模板中定义的宏则只能访问到传递给它的变量,或者全局变量。
这里有个打印表单元素的简单的宏
<pre>
{% macro input(name, value='', type='text', size=20) -%}
<input type="` type `" name="` name `" value="{{
value|e }}" size="` size `">
{%- endmacro %}
</pre>
这个宏能够在命名空间中被直接调用
<pre>
<p>{{ input('username') }}</p>
<p>{{ input('password', type='password') }}</p>
</pre>
若是这个宏在其它模板中,你必须先用import引入。
在一个模板中你能够访问三种特殊变量:
*'''varargs''' 等同于python语法中的"*args"
*'''kwargs''' 等同于python语法中的"**kwargs"
*'''caller''' 被call标签调用的宏,调用者会被存储在一个叫作caller的变量中。
宏其实也是一个对象,它有一些属性能够在模板中使用:
*'''name''' 宏的名称。{{ 'input.name':string }}
*'''arguments''' 宏能够接受的参数,这个属性是一个元组
*'''defaults''' 缺省值的元组
*'''catch_kwargs''' 这个宏是否能够接受关键字参数
*'''catch_varargs''' 这个宏是否能够接受索引位置参数
*'''caller''' 是否有caller变量,能够被call标签调用
Call
在某些状况下,你可能须要将一个宏对象传递到另一个宏中使用。为了实现此目的,你可使用call block。
<pre>
{% macro render_dialog(title, class='dialog') -%}
<div class="` class `">
<h2>` title `</h2>
<div class="contents">
{{ caller() }}
</div>
</div>
{%- endmacro %}
{% call render_dialog('Hello World') %}
This is a simple dialog rendered by using a macro and
a call block.
{% endcall %}
</pre>
在这里例子里,咱们用"call render_dialog"调用了宏render_dialog,其中,'hello world做为render_dialog的title参数。在render_dialog中用{{ caller() }}将 call block中的内容显示出来。
在使用 {{ caller() }} 时,也能够传入参数,以下例:
<pre>
{% macro dump_users(users) -%}
<ul>
{%- for user in users %}
<li><p>{{ user.username|e }}</p>{{ caller(user) }}</li>
{%- endfor %}
</ul>
{%- endmacro %}
{% call(user) dump_users(list_of_user) %}
<dl>
<dl>Realname</dl>
<dd>{{ user.realname|e }}</dd>
<dl>Description</dl>
<dd>` user`.`description `</dd>
</dl>
{% endcall %}
</pre>
赋值
在一个代码块内部你能够为一个变量赋值。在块(block, macro, loop)外部赋值的变量能够被从模板中导出,提供给其它模板使用。
一个赋值语句的用法以下例:
<pre>
{% navigation = [('index.html', 'Index'), ('about.html', 'About')] %}
</pre>
include
用include能够导入另一个模板到当前模板中
<pre>
{% include 'header.html' %}
Body
{% include 'footer.html' %}
</pre>
import
Jinja2支持将经常使用的代码放到宏中。这些宏能够放到不一样的模板中,而后用import语句导入来使用,这有点相似python的import 功能。须要注意的是,import导入的模板会被缓存,并且导入到模板不能访问当前模板的本地变量,它只能访问全局变量。
导入模板有两种方式,一是导入整个的模板做为一个变量,另外一个方法是从一个模板中导入指定的宏或者可导出的变量
下面咱们写一个名为"form.html"的模板, 这个模板做为一个公共模板提供给其它模板使用
<pre>
{% macro input(name, value='', type='text') -%}
<input type="` type `" value="{{ value|e }}" name="` name `">
{%- endmacro %}
{%- macro textarea(name, value='', rows=10, cols=40) -%}
<textarea name="` name `" rows="` rows `" cols="{{ cols
}}">{{ value|e }}</textarea>
{%- endmacro %}
</pre>
最简单和灵活的方式是把form.html整个导入到一个模板中
<pre>
{% import 'forms.html' as forms %}
<dl>
<dt>Username</dt>
<dd>{{ forms.input('username') }}</dd>
<dt>Password</dt>
<dd>{{ forms.input('password', type='password') }}</dd>
</dl>
<p>{{ forms.textarea('comment') }}</p>
</pre>
或者导入指定的内容(宏或者变量)到当前模板中
<pre>
{% from 'forms.html' import input as input_field, textarea %}
<dl>
<dt>Username</dt>
<dd>{{ input_field('username') }}</dd>
<dt>Password</dt>
<dd>{{ input_field('password', type='password') }}</dd>
</dl>
<p>{{ textarea('comment') }}</p>
</pre>
表达式
Jinja的表达式在模板中处处都是,它的语法很相似python,并且它很简单,即便不会python也能够很容易学会它。
字面值
字面值是最简单的表达式,它其实就是一个python的对象,在Jinja中有下面几种字面值:
字符串,数字,序列,元组,字典,bool类型。
它们的用法很python的很接近,以下面的例子:
<pre>
<ul>
{% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),
('downloads.html', 'Downloads')] %}
<li><a href="` href `">` caption `</a></li>
{% endfor %}
</ul>
</pre>
数字计算
Jinja支持一下几种操做符:
+,-,/,//(整除),%求余,*乘,**次方
逻辑操做
Jinja支持一下几种逻辑操做符,它们能够放在if块中使用:
and, or, not, ()
其它操做符
'''in '''
判断一个对象是否存在于另外一个序列或者元组中
<pre>
{{ 1 in [1, 2, 3] }}
</pre>
'''is'''
执行一个检查器
'''|'''
执行一个过滤器
'''~'''
链接字符串 '{{ "Hello " ~ name ~ "!" }}',若是name的值是'world, 显示的内容将是 "Hello world"
'''( )''' 调用函数
'''. / []''' 访问一个对象的属性
if表达式
Jinja支持内联表达式,在某些状况下很是有用,例如:
<pre>
{% extends layout_template if layout_template is defined else 'master.html' %}
</pre>
这个例子的意思是:若是变量layout_template已定义则导入,不然导入master.html
通用的语法规则是'''<do something> if <something is true> else <do something else>'''
内建过滤器
*'''abs(number)''' 返回数字的绝对值
*'''batch(value, linecount, fill_with=None)'''
:将一个序列以给定值分红若干片,若是给定了fill_with,则会将fill_with补充到未分配的部分。好比一个序列 ['a','b','c','d','e'], 用数值3分片将会获得[['a','b','c'], ['d','e']], 若是分片时指定fill_with=' ',结果将会是[['a','b','c'], ['d','e',' ']]
:这个过滤器的用处在于,若是你要在表格中显示一个很长的序列,每行显示5个,则能够用下面的方式打印:
<pre>
{% for row in seq|batch(3, ' ') %}
{% for item in row %}
</pre>
*'''capitalize(s)'''
首字符大写
*'''center(value, width=80)'''
生成一个长度为width的空字符串,将value放在中间
*'''default(value, default_value=u”, boolean=False)'''
若是value未定义,则显示default_value,若是value是一个bool型,须要将boolean置为true,这样当value为 false是将会打印缺省值
这个过滤器的别名是d
*'''dictsort(value, case_sensitive=False, by='key')'''
字典排序,case_sensitive决定是否大小写敏感,by决定是按照key排序仍是按value排序
*'''escape(s)'''
html字符转义,别名是e
*'''filesizeformat(value)'''
将一个大数字转换成KMG形式,如:1.3k,34g,25.3m等等
*'''first(seq)'''
返回序列的第一个值
*'''float(value, default=0.0)'''
将一个值转换成浮点数,若是转换失败则返回default
*'''forceescape(value)'''
无论value是否被转义过,一概进行html转义。好比value="<", 若是用“value|e|e”则会获得“<",而不是"&lt;",若是用forceescape则会得 到"&lt;"
*'''format(value, *args, **kwargs)'''
等同于python的"%s,%s" % (str1, str2)
*'''groupby(value, attribute)'''
相似SQL的group by,能够将一个序列里的对象/字典,按照attribute分组。以下例:
<pre>
<ul>
{% for group in persons|groupby('gender') %}
<li>` group`.`grouper `<ul>
{% for person in group.list %}
<li>` person`.`first_name ` ` person`.`last_name `</li>
{% endfor %}</ul></li>
{% endfor %}
</ul>
</pre>
也能够用下面的方式使用:
<pre>
<ul>
{% for grouper, list in persons|groupby('gender') %}
...
{% endfor %}
</ul>
</pre>
"grouper"是分组的值,在上面的例子中分别是“male”和“female”
*'''indent(s, width=4, indentfirst=False)'''
将文本s中每行的首字符缩进width个字符。indentfirst表示是否缩进第一行。
*'''int(value, default=0)'''
将value转换成整数,若是转换失败则返回default
*'''join(seq, d=u”)'''
将序列seq中的各个值用d字符链接起来造成一个字符串。
*'''last(seq)'''
序列的最后一个值。
*'''length(object)'''
序列或者字典的长度
别名:count
*'''list(value)'''
将value转换为序列,若是value是字符串,则将字符串转换为字符数组。
*'''lower(s)'''
将字符串转换为小写
*'''pprint(value, verbose=False)'''
debug时使用,能够打印变量的详细信息。
*'''random(seq)'''
随机从序列中取得一个值。
*'''replace(s, old, new, count=None)'''
将字符s中的old字符串替换为new字符串,若是给定了count,则最多替换count次。
*'''reverse(value)'''
将一个序列反转。
*'''round(value, precision=0, method='common')'''
浮点数求精。precision是小数点位数,method有common,ceil,floor三种。common是四舍五入,ceil和floor与 python的同名函数功能相同。
*'''safe(value)'''
若是当前模板设置了html自动转义,用此过滤器可使value不转义
*'''slice(value, slices, fill_with=None)'''
将序列分片,用fill_with字符填充最后一组子序列长度不足的部分。
*'''sort(value, reverse=False)'''
将序列按从小到大排序,reverse为true则按从大到小排序
*'''string(object)'''
将一个对象转换为unicode字符串
*'''striptags(value)'''
去掉字符串value中的html,xml标签
*'''sum(sequence, start=0)'''
统计数值序列的和。start表示从第几项开始计算
*'''title(s)'''
将字符串s中每一个单词首字符大写
*'''trim(value)'''
去掉字符串value中首尾的空格
*'''truncate(s, length=255, killwords=False, end='...')'''
截断一个字符串为length长度,末尾补end字符。killword为false则将最后一个单词完整保留,为True则将严格按照给定的长度截断。
*'''upper(s)'''
将字符串转换为大写
*'''urlize(value, trim_url_limit=None, nofollow=False)'''
*'''wordcount(s)'''
统计字符串中单词的个数
*'''wordwrap(s, pos=79, hard=False)'''
将字符串s按照pos长度换行。若是hard为True,则强制截断单词。
*'''xmlattr(d, autospace=True)'''
建立一个sgml/xml的属性字符串,例如:
<pre>
<ul{{ {'class': 'my_list', 'missing': none, 'id': 'list-%d'|format(variable)}|xmlattr }}>
...
</ul>
</pre>
结果会是这个样子:
<pre>
<ul class="my_list" id="list-42">
...
</ul>
</pre>
值会自动进行html转义,若是为未定义或者None则忽略。
*'''autospace''': 自动在首部添加空格.
内建检查器
*'''callable(object)'''
对象是否可调用
*'''defined(value)'''
对象是否已定义
*'''divisibleby(value, num)'''
value是否能够被num整除
*'''escaped(value)'''
是否已转义
*'''even(value)'''
是否为奇数
*'''iterable(value)'''
是否能够循环
*'''lower(value)'''
是否为小写
*'''none(value)'''
是否为None
*'''number(value)'''
是否为数字
*'''odd(value)'''
是否为偶数
*'''sameas(value, other)'''
value是否与other为同一个对象实例
*'''sequence(value)'''
是否为序列
*'''string(value)'''
是不是字符串
*'''undefined(value)'''
是否未定义
*'''upper(value)'''
是否为大写css