`
rockis
  • 浏览: 18870 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Jinja2简明手册

阅读更多
此文为本人翻译自Jinja官方手册,转载请注明出处
勘误请直接回复,或者发信至rockis@gmail.com

介绍
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.iteye.com/javascripts/tinymce/themes/advanced/langs/zh.js"></script><script type="text/javascript" src="http://www.iteye.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. 就是在渲染模板时自动把变量中的<>&等字符转换为&lt;&gt;&amp;。
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'.
Undefined Types 未定义类型
Undefined及其子类类被用来作为未定义类型。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()

异常

类名描述
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 %}
        &copy; 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转义,即把'<'转换为'&lt;','>'转换为'&gt;','&'转换为'&amp;'
通过给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>
在循环内部,你可以访问一些特殊的变量
VariableDescription
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='&nbsp;',结果将会是[['a','b','c'], ['d','e','&nbsp;']]
:这个过滤器的用处在于,如果你要在表格中显示一个很长的序列,每行显示5个,则可以用下面的方式打印:
<pre>
{% for row in seq|batch(3, '&nbsp;') %}
{% 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;",而不是"&amp;lt;",如果用forceescape则会得到"&amp;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)'''
是否为大写

分享到:
评论

相关推荐

    jinja2 chm python

    Jinja2 是一个 Python 的功能齐全的模板引擎。它有完整的 unicode 支持,一个可选 的集成沙箱执行环境,被广泛使用,以 BSD 许可证授权。

    jinja, Jinja2模板引擎.zip

    jinja, Jinja2模板引擎 Jinja2Jinja2是用纯 python 编写的模板引擎。 它提供了一个 Django 激发非xml语法,但支持内联表达式和可选的沙箱。下面是Jinja模板的一个小示例:{% extends 'base.html' %}

    flask+jinja2+echarts模板案例.rar

    flask+jinja2+echarts模板案例.rar

    Jinja2英文文档.pdf

    Jinja2英文文档.pdf

    Jinja2中文文档

    Jinja2中文文档 高清带书签

    flask_jinja2_web.zip

    flask jinja2 web 开发文档

    flask中jinja2使用全局变量

    flask中jinja2使用全局变量

    python2-jinja2-2.10-2.el7.noarch.rpm

    官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装

    python 利用jinja2模板生成html代码实例

    主要介绍了python 利用jinja2模板生成html代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

    实训报告-3-jinja2模板操作题

    实训报告-3-jinja2模板 使用Linux虚拟机模拟实现“一台控制端,两台被控端”的运维服务器架构模式,使用ansible自动化运维工具,调用template模块,使用jinja2模板完成指定的登录提示信息的实验。

    jinja2-python27

    Jinja2 is a full featured template engine for Python. It has full unicode support, an optional integrated sandboxed execution environment, widely used and BSD licensed.

    Jinja2-2.10.1-py2.py3-none-any.whl

    Jinja2-2.10.1-py2.py3-none-any.whl

    python-jinja2-26-2.6-3.el6.noarch.rpm

    python-jinja2-26-2.6-3.el6.noarch.rpm

    Jinja2-2.10

    Juinja2是Flask作者开发的一个模板系统

    Jinja2 文档

    Jinja2 is a modern and designer friendly templating language for Python, modelled after Django’s templates. It is fast, widely used and secure with the optional sandboxed template execution ...

    jinja2简单示例

    python jinja2简单示例 css效果 多级菜单实现效果 学习python

    Ansible-ansible-jinja2-templates.zip

    Ansible-ansible-jinja2-templates.zip,ansibleansible-jinja2-templates的jinja2模板示例,ansible是一个简单而强大的自动化引擎。它用于帮助配置管理、应用程序部署和任务自动化。

    pyjade, Django Jinja2和Mako的Jade 模板系统.zip

    pyjade, Django Jinja2和Mako的Jade 模板系统 PyJade PyJade是 python的一个高性能端口,它将任何. jade 源转换为每个模板语言( 。Django,Jinja2,Mako或者 Tornado ) 。命令行实用程序要简单地将转换输出到控制台...

    python包jinja2

    在windows下编译px4固件出错,下载此文件cd到此文件目录,然后python setup.py install即可。

Global site tag (gtag.js) - Google Analytics