jinja 模板设计者文档¶,jinja设计者


模板设计者文档¶

这份文档描述了模板引擎中的语法和语义结构,对于创建Jinja 模板是一份相当有用的参考。因为模板引擎非常灵活,应用中的配置会在分隔符和未定义值的行为方面与这里的配置有细微差异。

概要¶

模板仅仅是文本文件。它可以生成任何基于文本的格式(HTML、XML、CSV、LaTex等等)。它并没有特定的扩展名,.html.xml都是可以的。

模板包含变量表达式,这两者在模板求值的时候会被替换为值。模板中还有标签,控制模板的逻辑。模板语法的大量灵感来自于Django和Python 。

下面是一个最小的模板,它阐明了一些基础。我们会在文档中后面的部分解释细节:

<!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' ]  }}

知晓花括号不是变量的一部分,而是打印语句的一部分是重要的。如果你访问标签里的不带括号的变量。

如果变量或属性不存在,会返回一个未定义值。你可以对这类值做什么取决于应用的配置,默认的行为是它如果被打印,其求值为一个空字符串,并且你可以迭代它,但其它操作会失败。

实现

为方便起见,Jinja2中foo.bar在Python层中做下面的事情:

  • 检查foo上是否有一个名为bar的属性。
  • 如果没有,检查foo中是否有一个'bar'项。
  • 如果没有,返回一个未定义对象。

foo['bar']的方式相反,只在顺序上有细小差异:

  • 检查在foo中是否有一个'bar'项。
  • 如果没有,检查foo上是否有一个名为bar的属性。
  • 如果没有,返回一个未定义对象。

如果一个对象有同名的项和属性,这很重要。此外,有一个attr()过滤器,它只查找属性。

过滤器¶

变量可以通过过滤器修改。过滤器与变量用管道符号(|)分割,并且也可以用圆括号传递可选参数。多个过滤器可以链式调用,前一个过滤器的输出会被作为后一个过滤器的输入。

例如{{ name|striptags|title }}会移除name中的所有HTML标签并且改写为标题样式的大小写格式。过滤器接受带圆括号的参数,如同函数调用。这个例子会把一个列表用逗号连接起来: {{ list|join(', ') }}

下面的内置过滤器清单节介绍了所有的内置过滤器。

测试¶

除了过滤器,所谓的“测试”也是可用的。测试可以用于对照普通表达式测试一个变量。要测试一个变量或表达式,你要在变量后加上一个is以及测试的名称。例如,要得出一个值是否定义过,你可以用name is defined,这会根据name是否定义返回true或false 。

测试也可以接受参数。如果测试只接受一个参数,你可以省去括号来分组它们。例如, 下面的两个表达式做同样的事情:

{%  if  loop .index  is  divisibleby  3  %} 
{%  if  loop .index  is  divisibleby ( 3 )  %}

下面的内置测试清单章节介绍了所有的内置测试。

注释¶

要把模板中一行的部分注释掉,默认使用{# ... #}注释语法。这在调试或添加给你自己或其它模板设计者的信息时是有用的:

{# note: disabled template because we no longer use this 
    {% for user in users %} 
        ... 
    {% endfor %} 
#}

空白控制¶

默认配置中,模板引擎不会对空白做进一步修改,所以每个空白(空格、制表符、换行符等等)都会原封不动返回。如果应用配置了Jinja的trim_blocks,模板标签后的第一个换行符会被自动移除(像PHP中一样)。

此外,你也可以手动剥离模板中的空白。当你在块(比如一个for标签、一段注释或变量表达式)的开始或结束放置一个减号(-),可以移除块前或块后的空白:

{%  for  item  in  seq - %} 
    {{  item  }} 
{% - endfor  %}

这会产出中间不带空白的所有元素。如果seq19的数字的列表,输出会是123456789

如果开启了行语句,它们会自动去除行首的空白。

提示

标签和减号之间不能有空白。

有效的 :

{% - if  foo - %} ... {%  endif  %}

无效的 :

{% - if foo - %}... {%  endif  %}

转义¶

有时想要或什至必要让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>

行语句前缀可以出现在一行的任意位置,只要它前面没有文本。为了语句有更好的可读性,在块的开始(比如forifelif等等)以冒号结尾:

# for item in seq:
    ...
# endfor

提示

若有未闭合的圆括号、花括号或方括号,行语句可以跨越多行:

<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

模板继承¶

Jinja中最强大的部分就是模板继承。模板继承允许你构建一个包含你站点共同元素的基本模板“骨架”,并定义子模板可以覆盖的

听起来复杂,实际上很简单。从例子上手是最易于理解的。

基本模板¶

这个模板,我们会把它叫做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 %}标签定义了四个字幕版可以填充的块。所有的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标签应该是模板中的第一个标签。它前面的所有东西都会按照普通情况打印出来,而且可能会导致一些困惑。更多该行为的细节以及如何利用它,见 Null-Master退回

模板的文件名依赖于模板加载器。例如FileSystemLoader允许你用文件名访问其它模板。你可以使用斜线访问子目录中的模板:

{%  extends  "layout/default.html"  %}

这种行为也可能依赖于应用内嵌的Jinja 。注意子模板没有定义footer块,会使用父模板中的值。

你不能在同一个模板中定义多个同名的{% block %}标签。因为块标签以两种方向工作,所以存在这种限制。即一个块标签不仅提供一个可以填充的部分,也在父级定义填充的内容。如果同一个模板中有两个同名的{% blok %}标签,父模板无法获知要使用哪一个块的内容。

如果你想要多次打印一个块,无论如何你可以使用特殊的self变量并调用与块同名的函数:

<title> {%  block  title  %}{%  endblock  %} </title> 
<h1> {{  self.title ()  }} </h1> 
{%  block  body  %}{%  endblock  %}

Super块¶

可以调用super来渲染父级块的内容。这会返回父级块的结果:

{%  block  sidebar  %} 
    <h3> Table Of Contents </h3>
    ...
    {{  super ()  }} 
{%  endblock  %}

命名块结束标签¶

Jinja2 允许你在块的结束标签中加入的名称来改善可读性:

{%  block  sidebar  %} 
    {%  block  inner_sidebar  %}
        ...
    {%  endblock  inner_sidebar  %} 
{%  endblock  sidebar  %}

无论如何,endblock后面的名称一定与块名匹配。

嵌套块和作用域¶

嵌套块可以胜任更复杂的布局。而默认的块不允许访问块外作用域中的变量:

{%  for  item  in  seq  %} 
    <li> {%  block  loop_item  %}{{  item  }}{%  endblock  %} </li> 
{%  endfor  %}

这个例子会输出空的<li>项,因为item在块中是不可用的。其原因是,如果块被子模板替换,变量在其块中可能是未定义的或未被传递到上下文。

从Jinja 2.2开始,你可以显式地指定在块中可用的变量,只需在块声明中添加 scoped修饰,就把块设定到作用域中:

{%  for  item  in  seq  %} 
    <li> {%  block  loop_item  scoped  %}{{  item  }}{%  endblock  %} </li> 
{%  endfor  %}

当覆盖一个块时,不需要提供scoped修饰。

模板对象¶

Changed in version 2.4.

当一个模板对象被传递到模板上下文,你也可以从那个对象继承。假设调用代码传递layout_template布局模板到环境,这段代码会工作:

{%  extends  layout_template  %}

之前layout_template变量一定是布局模板文件名的字符串才能工作。

HTML转义¶

当从模板生成HTML 时,始终有这样的风险:变量包含影响已生成HTML 的字符。有两种解决方法:手动转义每个字符或默认自动转义所有的东西。

Jinja 两者都支持,使用哪个取决于应用的配置。默认的配置未开启自动转义有这样几个原因:

  • 转义所有非安全值的东西也意味着Jijna 转义已知不包含HTML 的值,比如数字,对性能有巨大影响。
  • 关于变量安全性的信息是易碎的。可能会发生强制标记一个值为安全或非安全的情况, 而返回值会被作为HTML 转义两次。

使用手动转义¶

如果启用了手动转义,按需转义变量就是你的责任。要转义什么?如果你有一个可能包含><&"字符的变量,你必须转义它,除非变量中的HTML有可信的良好格式。转义通过用管道传递到过滤器|e 来实现: { { user.username|e }}

使用自动转义¶

当启用了自动转移,默认会转移一切,除非值被显式地标记为安全的。可以在应用中标记,也可以在模板中使用|safe过滤器标记。这种方法的主要问题是Python本身没有被污染的值的概念,所以一个值是否安全的信息会丢失。如果这个信息丢失,会继续转义,你最后会得到一个转义了两次的内容。

但双重转义很容易避免,只需要依赖Jinja2 提供的工具而不使用诸如字符串模运算符这样的Python 内置结构。

返回模板数据(宏、superself.BLOCKNAME)的函数,其返回值总是被标记为安全的。

模板中的字符串字面量在自动转义中被也被视为是不安全的。这是因为安全的字符串是一个对Python 的扩展,而不是每个库都能妥善地使用它。

控制结构清单¶

控制结构指的是所有的那些可以控制程序流的东西——条件(比如if/elif/ekse )、 for循环、以及宏和块之类的东西。控制结构在默认语法中以{% .. %}块的形式出现。

For ¶

遍历序列中的每项。例如,要显示一个由users`变量提供的用户列表:

<h1> Members </h1> 
<ul> 
{%  for  user  in  users  %} 
  <li> {{  user.username | e  }} </li> 
{%  endfor  %} 
</ul>

因为模板中的变量保留它们的对象属性,可以迭代像dict的容器:

<dl> 
{%  for  key ,  value  in  my_dict.iteritems ()  %} 
    <dt> {{  key | e  }} </dt> 
    <dd> {{  value | e  }} </dd> 
{%  endfor  %} 
</dl>

注意无论如何字典通常是无序的,所以你可能需要把它作为一个已排序的列表传入到模板或使用dictsort过滤器。

在一个for 循环块中你可以访问这些特殊的变量:

变量 描述
loop.index 当前循环迭代的次数(从1 开始)
loop.index0 当前循环迭代的次数(从0 开始)
loop.revindex 到循环结束需要迭代的次数(从1 开始)
loop.revindex0 到循环结束需要迭代的次数(从0 开始)
loop.first 如果是第一次迭代,为True 。
loop.last 如果是最后一次迭代,为True 。
loop.length 序列中的项目数。
loop.cycle 在一串序列间期取值的辅助函数。见下面的解释。

在for循环中,可以使用特殊的loop.cycle辅助函数,伴随循环在一个字符串/变量列表中周期取值:

{%  for  row  in  rows  %} 
    <li  class= " {{  loop .cycle ( 'odd' ,  'even' )  }} " > {{  row  }} </li> 
{%  endfor  %}

从Jinja 2.1开始,一个额外的cycle辅助函数允许循环限定外的周期取值。更多信息请阅读全局函数清单

与Python中不同,模板中的循环内不能breakcontinue。但你可以在迭代中过滤序列来跳过项目。下面的例子中跳过了所有隐藏的用户:

{%  for  user  in  users  if  not  user.hidden  %} 
    <li> {{  user.username | e  }} </li> 
{%  endfor  %}

好处是特殊的loop可以正确地计数,从而不计入未迭代过的用户。

如果因序列是空或者过滤移除了序列中的所有项目而没有执行循环,你可以使用 else渲染一个用于替换的块:

<ul> 
{%  for  user  in  users  %} 
    <li> {{  user.username | e  }} </li> 
{%  else  %} 
    <li><em> no users found </em></li> 
{ %  endfor  %} 
</ul>

也可以递归地使用循环。当你处理诸如站点地图之类的递归数据时很有用。要递归地使用循环,你只需要在循环定义中加上recursive修饰,并在你想使用递归的地方,对可迭代量调用loop变量。

下面的例子用递归循环实现了站点地图:

<ul  class= "sitemap" > 
{% - for  item  in  sitemap  recursive  %} 
    <li><a  href= " {{  item.href | e  }} " > {{  item.title  }} </a> 
    {% - if  item.children - %} 
        <ul  class= "submenu" > {{  loop ( item.children )  }} </ul> 
    {% - endif  %} </li>
{% - endfor %} 
</ul>

If ¶

Jinja中的if语句可比Python中的if语句。在最简单的形式中,你可以测试一个变量是否未定义,为空或false:

{%  if  users  %} 
<ul> 
{%  for  user  in  users  %} 
    <li> {{  user.username | e  }} </li> 
{%  endfor  %} 
</ul> 
{%  endif  %}

像在Python中一样,用elifelse来构建多个分支。你也可以用更复杂的 表达式 :

{%  if  kenny.sick  %}
    Kenny is sick.
{%  elif  kenny.dead  %}
    You killed Kenny! You bastard!!!
{%  else  %}
    Kenny looks okay --- so far
{%  endif  %}

If也可以被用作内联表达式并作为 循环过滤

宏¶

宏类似常规编程语言中的函数。它们用于把常用行为作为可重用的函数,取代手动重复的工作。

这里是一个宏渲染表单元素的小例子:

{%  macro  input ( name ,  value = '' ,  type = 'text' ,  size = 20 ) - %} 
    <input  type= " {{  type  }} "  name= " {{  name  }} "  value= " {{ 
        value | e  }} "  size= " {{  size  }} " > 
{% - endmacro  %}

在命名空间中,宏之后可以像函数一样调用:

<p> {{  input ( 'username' )  }} </p> 
<p> {{  input ( 'password' ,  type = 'password' )  }} </p>

如果宏在不同的模板中定义,你需要首先使用import

在宏内部,你可以访问三个特殊的变量:

varargs
如果有多于宏接受的参数个数的位置参数被传入,它们会作为列表的值保存在 varargs变量上。
kwargs
varargs,但只针对关键字参数。所有未使用的关键字参数会存储在这个特殊变量中。
caller
如果宏通过call标签调用,调用者会作为可调用的宏被存储在这个变量中。

宏也可以暴露某些内部细节。下面的宏对象属性是可用的:

name
宏的名称。{{ input.name }}会打印input
arguments
一个宏接受的参数名的元组。
defaults
默认值的元组。
catch_kwargs
如果宏接受额外的关键字参数(也就是访问特殊的kwargs变量),为true
catch_varargs
如果宏接受额外的位置参数(也就是访问特殊的varargs变量),为true
caller
如果宏访问特殊的caller变量且由call标签调用,为true

如果一个宏的名称以下划线开始,它不是导出的且不能被导入。

调用¶

在某些情况下,需要把一个宏传递到另一个宏。为此,可以使用特殊的call块。下面的例子展示了如何让宏利用调用功能:

{%  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  %}

也可以向调用块传递参数。这在为循环做替换时很有用。总而言之,调用块的工作方式几乎与宏相同,只是调用块没有名称。

这里是一个带参数的调用块的例子:

{%  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  %}

过滤器¶

过滤器段允许你在一块模板数据上应用常规Jinja2过滤器。只需要把代码用 filter节包裹起来:

{%  filter  upper  %}
    This text becomes uppercase
{%  endfilter  %}

赋值¶

在代码块中,你也可以为变量赋值。在顶层的(块、宏、循环之外)赋值是可导出的,即可以从别的模板中导入。

赋值使用set标签,并且可以为多个变量赋值:

{%  set  navigation  =  [( 'index.html' ,  'Index' ),  ( 'about.html' ,  'About' )]  %} 
{%  set  key ,  value  =  call_something ()  %}

继承¶

extends标签用于从另一个模板继承。你可以在一个文件中使用多次继承,但是只会执行其中的一个。见上面的关于模板继承的节。

块¶

块用于继承,同时作为占位符和用于替换的内容。模板继承 节中详细地介绍了块。

包含¶

include语句用于包含一个模板,并在当前命名空间中返回那个文件的内容渲染结果:

{%  include  'header.html'  %}
    Body
{%  include  'footer.html'  %}

被包含的模板默认可以访问活动的上下文中的变量。更多关于导入和包含的上下文行为见导入上下文行为

从Jinja 2.2开始,你可以把一句include用ignore missing标记,这样如果模板不存在,Jinja会忽略这条语句。当与withwithout context 语句联合使用时,它必须被放在上下文可见性语句之前。这里是一些有效的例子:

{%  include  "sidebar.html"  ignore missing  %} 
{%  include  "sidebar.html"  ignore missing  with context  %} 
{%  include  "sidebar.html"  ignore missing  without context  %}

New in version 2.2.

你也可以提供一个模板列表,它会在包含前被检查是否存在。第一个存在的模板会被包含进来。如果给出了ignore missing,且所有这些模板都不存在,会退化至不做任何渲染,否则将会抛出一个异常。

例子:

{%  include  [ 'page_detailed.html' ,  'page.html' ]  %} 
{%  include  [ 'special_sidebar.html' ,  'sidebar.html' ]  ignore missing  %}

Changed in version 2.4:如果传递一个模板对象到模板上下文,你可以用include包含这个对象。

导入¶

Jinja2支持在宏中放置经常使用的代码。这些宏可以被导入,并不同的模板中使用。这与Python中的import语句类似。要知道的是,导入量会被缓存,并且默认下导入的模板不能访问当前模板中的非全局变量。更多关于导入和包含的上下文行为见 导入上下文行为

有两种方式来导入模板。你可以把整个模板导入到一个变量或从其中导入请求特定的宏/导出量。

比如我们有一个渲染表单(名为forms.html)的助手模块:

{%  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  %}

最简单灵活的方式是把整个模块导入为一个变量。这样你可以访问属性:

{%  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>

此外你也可以从模板中导入名称到当前的命名空间:

{%  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>

名称以一个或更多下划线开始的宏和变量是私有的,不能被导入。

Changed in version 2.4:如果传递一个模板对象到模板上下文,从那个对象中导入。

导入上下文行为¶

默认下,每个包含的模板会被传递到当前上下文,而导入的模板不会。这样做的原因是导入量不会像包含量被缓存,因为导入量经常只作容纳宏的模块。

无论如何,这当然也可以显式地更改。通过在import/include声明中直接添加 with contextwithout context,当前的上下文可以传递到模板,而且不会自动禁用缓存。

这里有两个例子:

{%  from  'forms.html'  import  input  with context  %} 
{%  include  'header.html'  without context  %}

提示

在Jinja 2.0 中,被传递到被包含模板的上下文不包含模板中定义的变量。事实上,这不能工作:

{%  for  box  in  boxes  %} 
    {%  include  "render_box.html"  %} 
{%  endfor  %}

在Jinja 2.0中,被包含的模板render_box.html 不能访问 box。从Jinja 2.1开始,render_box.html 可以这么做。

表达式¶

Jinja 中到处都允许使用基本表达式。这像常规的Python 一样工作,即使你不用Python 工作,你也会感受到其带来的便利。

字面量¶

表达式最简单的形式就是字面量。字面量表示诸如字符串和数值的Python 对象。下面的字面量是可用的:

“Hello World”:
双引号或单引号中间的一切都是字符串。无论何时你需要在模板中使用一个字符串(比如函数调用、过滤器或只是包含或继承一个模板的参数),它们都是有用的。
42 / 42.23:
直接写下数值就可以创建整数和浮点数。如果有小数点,则为浮点数,否则为整数。记住在Python里,4242.0是不一样的。
['list', 'of', 'objects']:

一对中括号括起来的东西是一个列表。列表用于存储和迭代序列化的数据。例如你可以容易地在for 循环中用列表和元组创建一个链接的列表:

<ul> 
{%  for  href ,  caption  in  [( 'index.html' ,  'Index' ),  ( 'about.html' ,  'About' ), 
                         ( 'downloads.html' ,  'Downloads' )]  %} 
    < li><a  href= " {{  href  }} " > {{  caption  }} </a></li> 
{%  endfor  %} 
</ul>
('tuple', 'of', 'values'):
元组与列表类似,只是你不能修改元组。如果元组中只有一个项,你需要以逗号结尾它。元组通常用于表示两个或更多元素的项。更多细节见上面的例子。
{'dict': 'of', 'key': 'and', 'value': 'pairs'}:
Python中的字典是一种关联键和值的结构。键必须是唯一的,并且键必须只有一个值。字典在模板中很少使用,罕用于诸如xmlattr()过滤器之类。
true / false:
true 永远是true ,而false 始终是false 。

提示

特殊常量truefalsenone实际上是小写的。因为这在过去会导致混淆,过去True扩展为一个被认为是false的未定义的变量。所有的这三个常量也可以被写成首字母大写(TrueFalseNone)。尽管如此,为了一致性(所有的Jinja标识符是小写的),你应该使用小写的版本。

算术¶

Jinja 允许你用计算值。这在模板中很少用到,但是为了完整性允许其存在。支持下面的运算符:

+
把两个对象加到一起。通常对象是素质,但是如果两者是字符串或列表,你可以用这种方式来衔接它们。无论如何这不是首选的连接字符串的方式!连接字符串见~ 运算符。{{ 1 + 1 }}等于2
-
用第一个数减去第二个数。{{ 3 - 2 }}等于1
/
对两个数做除法。返回值会是一个浮点数。 {{ 1 / 2 }}等于{{ 0.5 }}
//
对两个数做除法,返回整数商。 {{ 20 // 7 }}等于2
%
计算整数除法的余数。{{ 11 % 7 }}等于4
*
用右边的数乘左边的操作数。{{ 2 * 2 }}会返回4。也可以用于重复一个字符串多次。{{ '=' * 80 }}会打印80个等号的横条。
**
取左操作数的右操作数次幂。{{ 2**3 }}会返回8

比较¶

==
比较两个对象是否相等。
!=
比较两个对象是否不等。
>
如果左边大于右边,返回true
>=
如果左边大于等于右边,返回true
<
如果左边小于右边,返回true
<=
如果左边小于等于右边,返回true

逻辑¶

对于if语句,在for过滤或if表达式中,它可以用于联合多个表达式:

and
如果左操作数和右操作数同为真,返回true 。
or
如果左操作数和右操作数有一个为真,返回true 。
not
对一个表达式取反(见下)。
(expr)
表达式组。

提示

is in运算符同样支持使用中缀记法: foo is not bar foo not in bar而不是 not foo is bar not foo in bar。所有的其它表达式需要前缀记法 not (foo and bar)

其它运算符¶

下面的运算符非常有用,但不适用于其它的两个分类:

in
运行序列/映射包含检查。如果左操作数包含于右操作数,返回true 。比如 {{ 1 in [1,2,3] }}会返回true 。
is
运行一个测试
|
应用一个过滤器
~
把所有的操作数转换为字符串,并且连接它们。 {{ "Hello " ~ name ~ "!" }}会返回(假设name值为 ''John'Hello John!
()
调用一个可调用量: {{ post.render() }}。在圆括号中,你可以像在python中一样使用位置参数和关键字参数: {{ post.render(user, full=true) }}
. / []
获取一个对象的属性。(见变量

If表达式¶

同样,也可以使用内联的if表达式。这在某些情况很有用。例如你可以用来在一个变量定义的情况下才继承一个模板,否则继承默认的布局模板:

{%  extends  layout_template  if  layout_template  is  defined  else  'master.html'  %}

一般的语法是<do something> if <something is true> else <do something else>

else部分是可选的。如果没有显式地提供else块,会求值一个未定义对象:

{{ '[%s]' % page.title if page.titl

相关内容

    暂无相关文章