Jinja教程(轉)

介紹

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. 但在實際應用中并不推薦此用法:

 

>>> from Jinja2 import Template

>>> template = Template('Hello {{ name }}!')

>>> template.render(name='World')

u'Hello World!'

這個例子使用字符串作為模板內容創建了一個Template實例,然后用"name='World'"作為參數調用"render方法,將內容中 的'name'替換為"World",最終返回渲染過的字符串--"u'Hello World!'"。

API

Environment

Environment是Jinja2中的一個核心類,它的實例用來保存配置、全局對象,以及從本地文件系統或其它位置加載模板。

多數應用會在初始化時創建Environment實例,然后用它來加載模板。當然,如果系統有必要使用不同的配置,也可以創建多個 Environment實例一起使用。

配置Jinja2為你的應用加載模板的最簡單的方式可以像下面這樣:

from Jinja2 import Environment, PackageLoader

env = Environment(loader=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=, 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實例。

方法:

render(*args, **kwargs)

此方法接受與“dict”相同的構建器參數:一個dict,dict的子類,或者一些關鍵字參數。下面兩種調用方式是等價的:

template.render(knights='that say nih')

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

generate(*args, **kwargs)

此方法會一段一段的渲染模板,而不是一次性的將整個模板渲染成目標文本。這對產生非常大的模板時非常有用。調用此方法會返回一個產生器 (generator),它可以....

stream(*args, **kwargs)

與generate功能類似,只不過此方法返回一個TemplateStream module

此方法用來在模板運行時導入, 也可以用來在python代碼中訪問導出的模板變量.

>>> t = Template('{% macro foo() %}42{% endmacro %}23')

>>> unicode(t.module)

u'23'

>>> t.module.foo()

u'42'.

Unde?ned Types 未定義類型

Unde?ned及其子類類被用來作為未定義類型。Environment的構建器可以指定undefined參數,它可以是undefined types中的任意一個,或者是Undefined的子類。當模板引擎無法找到一個名稱或者一個屬性時,使用的Undefined會決定哪些操作可以正常 進行,哪些不可以。

'''class Undefined(hint=None, obj=None, name=None)'''

缺省undefined類型。此未定義類型可以打印或者作為sequence迭代。但是不能做其它操作,否則會拋出UndefinedError

 

foo = Undefined(name='foo')

>>> str(foo)

''

>>> not foo

True

>>> foo + 42

Traceback (most recent call last):

...

Jinja2.exceptions.UndefinedError: 'foo' is undefined

'''class DebugUndefined(hint=None, obj=None, name=None)'''

 

>>> foo = DebugUndefined(name='foo')

>>> str(foo)

'{{ foo }}'

>>> not foo

True

>>> foo + 42

Traceback (most recent call last):

...

Jinja2.exceptions.UndefinedError: 'foo' is undefined

'''class StrictUndefined(hint=None, obj=None, name=None)'''

 

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

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。

下面是一個簡單的模板,它包含的了幾個模板中的基本元素,在之后的文檔中會對這些元素做詳細說明。

 

? ? ?

? ? ?

{{% for item in navigation %}}

? ? ? ? ?

  • {{ item.caption }}
  • {% endfor %}

    ? ? ?

    My Webpage

    {{ a_variable }}

    這個模板中包含了兩種標記符"{% ... %}"與"{{ .. }}", 前者用來執行一個循環或者一個賦值語句,后者用來打印一個變量。

    變量

    你可以傳遞python的變量給模板,用來替換模板中的標記。這些變量可以是任何Python對象。在模板中可以直接操作傳入的變量對象,也可以 訪問這些變量的屬性。

    訪問變量屬性有兩種方式,一種是用"obj.attr"的方式,另一種是類似字典的方式:"obj['attr']".

     

    {{ foo.bar }}

    {{ foo['bar'] }}

    注意,上面的'{{ .. }}是Jinja的用來打印變量標記。如果要在其它標簽中訪問變量,則不能在變量名旁邊加花括號。

    過濾器(filters)

    變量可以在模板中被過濾器修改. 使用過濾器的方式比較類似管道(pipe)操作。如:

     ?'{{ name|striptags|title }}'

    這個例子的意思是:將name變量用striptags消除變量值中的tag(用<>括起來的內容),再用title過濾器將首字符 大寫。

    過濾器也可以接受參數,用起來比較像調用函數

     '{{ list|join(', ') }}'

    內建過濾器介紹參見內建過濾器一節。

    檢查器(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"的模板,它包含下面的內容:

     

    {% block head %}

    ? ?

    ? ?

    {% endblock %}

    ? ?

    {% block content %}{% endblock %}

    ? ?

    {% block footer %}

    ? Copyright 2008 by you.

    {% endblock %}

    在這個模板中有很多'block', 這些block中間的內容,我們將會在子模板中用其它內容替換。

    子模板

    我們再寫一個名為"child.html"的模板,內容如下:

     

    {% extends "base.html" %}

    {% block title %}Index{% endblock %}

    {% block head %}

    {{ super() }}

    ? ?

    .important { color: #336699; }

    {% endblock %}

    {% block content %}

    ? ?

    Index

    ? ?

    Welcome on my awsome homepage.

    ? ?

    {% endblock %}

    :在這個模板的第一行,我們用{% extends "base.html" %}標明,這個模板將繼承base.html.

    在隨后的內容中包含了很多跟base.html中相同的block,如title,content,這些block中的內容將會替換 base.html的內容后輸出.

    :extends后面的模板名稱的寫法依賴于此模板使用的模板加載器, 比如如果要使用FileSystemLoader,你可以在模板文件名中加入文件的文件夾名,如:

     

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

    在base.html中,我們定義了block “footer”,這個block在子模板中沒有被重定義,那么Jinja會直接使用父模板中的內容輸出。

    另外要注意,在同一個模板中不能定義名稱相同的block。

    如果你要在模板中多次打印同一個block,可以用用self變量加上block的名字:

     

    {{ self.title() }}

    {% block body %}{% endblock %}

    和Python不同的地方是,Jinja不支持多繼承。

    super block

    如果要在子模板中重寫父模板的block中打印被重寫的block的內容,可以調用super關鍵字。

     

    {% block sidebar %}

    ? ?

    Table Of Contents

    ...

    {{ super() }}

    {% endblock %}

     

    HTML轉義

    :我們傳遞給模板的變量中可能會有一些html標記符,這些標記符也許會影響我們頁面的正常顯示,而且會給我們的站點帶來跨站腳本攻擊的隱患。

    Jinja提供了兩種方式-自動或者手工來對變量值進行html轉義,即把'<'轉換為'<','>'轉換為 '>','&'轉換為'&'

    通過給Environment或Template的構建器傳遞autoescape參數,可以設置自動轉義與否。

    手動轉義

    這種方式需要我們使用過濾器轉換我們需要轉義的變量

    '{{ user.username|e }}'. 這里'e'就是轉義過濾器

    自動轉義

    這種方式會在打印變量時自動進行轉義。除非使用'safe'過濾器標明不需要轉義:

     

    '{{ user.username|safe }}'.

    結構控制標記

    Jinja中的控制標記包括:條件判斷標記(if/elif/else),循環控制(for-loop),另外還有macro(宏)和上文中提到 的block。

    for

    循環打印一個序列,例如:

     

    Members

    {% for user in users %}

    ?

  • {{ user.username|e }}
  • {% endfor %}

    在循環內部,你可以訪問一些特殊的變量

    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 是 一個幫助性質的函數,可以接受兩個字符串參數,如果當前循環索引是偶數,則顯示第一個字符串,是奇數則顯示第二個字符串。它常被在表格中用來用不同的背景 色區分相鄰的行。

     

    {% for row in rows %}

    ? ?

  • {{ row }}
  • {% endfor %}

    需要注意的是,Jinja的循環不支持break和continue標記。你可以對需要迭代的sequence使用過濾器來達到與break和 continue相同的目的。

    下面的例子中,如果user.hidden屬性為true的則continue

     

    {% for user in users if not user.hidden %}

    ? ?

  • {{ user.username|e }}
  • {% endfor %}

    Jinja的for語句有一個和python相同的用法,那就是“else':當無循環時顯示else中的內容,如下例:

     

    {% for user in users %}

    ? ?

  • {{ user.username|e }}
  • {% else %}

    ? ?

  • no users found
  • {% endif %}

    if

    if語句用來在Jinja中做比較判斷,比較常見的用法是判斷一個變量是否已定義,是否非空,是否為true

     

    {% if users %}

    {% for user in users %}

    ? ?

  • {{ user.username|e }}
  • {% endfor %}

    {% endif %}

    和python一樣,也可以使用elif和else

     

    {% if kenny.sick %}

    Kenny is sick.

    {% elif kenny.dead %}

    You killed Kenny! ?You bastard!!!

    {% else %}

    Kenny looks okay --- so far

    {% endif %}

    if語句也可以被用來做內聯表達式或者for語句過濾器。

    宏(Macro)

    宏的作用和函數比較類似。用來把一部分常用的代碼封裝起來,避免重復性的工作。

    宏可以定義在一個幫助性質的模板中,用imported的方式被其它模板引用;也可以在模板中定義并直接使用。這兩種方式有個顯著的不同:在模板 中定義的宏可以訪問傳給模板的上下文變量;在其它模板中定義的宏則只能訪問到傳遞給它的變量,或者全局變量。

    這里有個打印表單元素的簡單的宏

     

    {% macro input(name, value='', type='text', size=20) -%}

    value|e }}" size="{{ size }}">

    {%- endmacro %}

    這個宏可以在命名空間中被直接調用

     

    {{ input('username') }}

    {{ input('password', type='password') }}

    如果這個宏在其它模板中,你必須先用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。

     

    {% macro render_dialog(title, class='dialog') -%}

    ? ?

    ? ? ? ?

    {{ title }}

    ? ? ? ?

    {{ caller() }}

    {%- endmacro %}

    {% call render_dialog('Hello World') %}

    This is a simple dialog rendered by using a macro and

    a call block.

    {% endcall %}

    在這里例子里,我們用"call render_dialog"調用了宏render_dialog,其中,'hello world作為render_dialog的title參數。在render_dialog中用{{ caller() }}將 call block中的內容顯示出來。

    在使用 {{ caller() }} 時,也可以傳入參數,如下例:

     

    {% macro dump_users(users) -%}

    ? ?

    {%- for user in users %}

    ? ? ? ?

  • {{ user.username|e }}

    {{ caller(user) }}
  • {%- endfor %}

    {%- endmacro %}

    {% call(user) dump_users(list_of_user) %}

    ? ?

    ? ? ? ?

    Realname

    ? ? ? ?

    {{ user.realname|e }}

    ? ? ? ?

    Description

    ? ? ? ?

    {{ user.description }}

    {% endcall %}

    賦值

    在一個代碼塊內部你可以為一個變量賦值。在塊(block, macro, loop)外部賦值的變量可以被從模板中導出,提供給其它模板使用。

    一個賦值語句的用法如下例:

     

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

    include

    用include可以導入另外一個模板到當前模板中

     

    {% include 'header.html' %}

    Body

    {% include 'footer.html' %}

    import

    Jinja2支持將常用的代碼放到宏中。這些宏可以放到不同的模板中,然后用import語句導入來使用,這有點類似python的import 功能。需要注意的是,import導入的模板會被緩存,而且導入到模板不能訪問當前模板的本地變量,它只能訪問全局變量。

    導入模板有兩種方式,一是導入整個的模板作為一個變量,另一個方法是從一個模板中導入指定的宏或者可導出的變量

    下面我們寫一個名為"form.html"的模板, 這個模板作為一個公共模板提供給其它模板使用

     

    {% macro input(name, value='', type='text') -%}

    {%- endmacro %}

    {%- macro textarea(name, value='', rows=10, cols=40) -%}

    }}">{{ value|e }}

    {%- endmacro %}

    最簡單和靈活的方式是把form.html整個導入到一個模板中

     

    {% import 'forms.html' as forms %}

    ? ?

    Username

    ? ?

    {{ forms.input('username') }}

    ? ?

    Password

    ? ?

    {{ forms.input('password', type='password') }}

    {{ forms.textarea('comment') }}

    或者導入指定的內容(宏或者變量)到當前模板中

     

    {% from 'forms.html' import input as input_field, textarea %}

    ? ?

    Username

    ? ?

    {{ input_field('username') }}

    ? ?

    Password

    ? ?

    {{ input_field('password', type='password') }}

    {{ textarea('comment') }}

    表達式

    Jinja的表達式在模板中到處都是,它的語法很類似python,而且它很簡單,即使不會python也可以很容易學會它。

    字面值

    字面值是最簡單的表達式,它其實就是一個python的對象,在Jinja中有下面幾種字面值:

    字符串,數字,序列,元組,字典,bool類型。

    它們的用法很python的很接近,如下面的例子:

     

    {% for href, caption in [('index.html', 'Index'), ('about.html', 'About'),

    ('downloads.html', 'Downloads')] %}

    ? ?

  • {{ caption }}
  • {% endfor %}

    數字計算

    Jinja支持一下幾種操作符:

    +,-,/,//(整除),%求余,*乘,**次方

    邏輯操作

    Jinja支持一下幾種邏輯操作符,它們可以放在if塊中使用:

    and, or, not, ()

    其它操作符

    '''in '''

    判斷一個對象是否存在于另一個序列或者元組中

     

    {{ 1 in [1, 2, 3] }}

    '''is'''

    執行一個檢查器

    '''|'''

    執行一個過濾器

    '''~'''

    連接字符串 '{{ "Hello " ~ name ~ "!" }}',如果name的值是'world, 顯示的內容將是 "Hello world"

    '''( )''' 調用函數

    '''. / []''' 訪問一個對象的屬性

    if表達式

    Jinja支持內聯表達式,在某些情況下非常有用,例如:

     

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

    這個例子的意思是:如果變量layout_template已定義則導入,否則導入master.html

    通用的語法規則是''' if ?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個,則可以用下面的方式打印:

     

    {% for row in seq|batch(3, ' ') %}

    {% for item in row %}

    *'''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”則會得到“<",而不是"<",如果用forceescape則會得 到"<"

    *'''format(value, *args, **kwargs)'''

    等同于python的"%s,%s" % (str1, str2)

    *'''groupby(value, attribute)'''

    類似SQL的group by,可以將一個序列里的對象/字典,按照attribute分組。如下例:

     

    {% for group in persons|groupby('gender') %}

    ? ?

  • {{ group.grouper }}

  • {% for person in group.list %}

    ? ? ? ?

  • {{ person.first_name }} {{ person.last_name }}
  • {% endfor %}

    {% endfor %}

    也可以用下面的方式使用:

     

    {% for grouper, list in persons|groupby('gender') %}

    ...

    {% endfor %}

    "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的屬性字符串,例如:

     

    ...

    結果會是這個樣子:

     

    ...

    值會自動進行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)'''

    是否為大寫

    最后編輯于
    ?著作權歸作者所有,轉載或內容合作請聯系作者
    • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
      沈念sama閱讀 227,401評論 6 531
    • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
      沈念sama閱讀 98,011評論 3 413
    • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
      開封第一講書人閱讀 175,263評論 0 373
    • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
      開封第一講書人閱讀 62,543評論 1 307
    • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
      茶點故事閱讀 71,323評論 6 404
    • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
      開封第一講書人閱讀 54,874評論 1 321
    • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
      沈念sama閱讀 42,968評論 3 439
    • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
      開封第一講書人閱讀 42,095評論 0 286
    • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
      沈念sama閱讀 48,605評論 1 331
    • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
      茶點故事閱讀 40,551評論 3 354
    • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
      茶點故事閱讀 42,720評論 1 369
    • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
      沈念sama閱讀 38,242評論 5 355
    • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
      茶點故事閱讀 43,961評論 3 345
    • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
      開封第一講書人閱讀 34,358評論 0 25
    • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
      開封第一講書人閱讀 35,612評論 1 280
    • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
      沈念sama閱讀 51,330評論 3 390
    • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
      茶點故事閱讀 47,690評論 2 370

    推薦閱讀更多精彩內容

    • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
      卡卡羅2017閱讀 134,775評論 18 139
    • 項目配置 設置為DEBUG模式: 默認情況下flask不會開啟DEBUG模式,開啟DEBUG模式后,flask會在...
      編程小蟬閱讀 3,582評論 0 9
    • Spring Boot 參考指南 介紹 轉載自:https://www.gitbook.com/book/qbgb...
      毛宇鵬閱讀 46,887評論 6 342
    • 1. Java基礎部分 基礎部分的順序:基本語法,類相關的語法,內部類的語法,繼承相關的語法,異常的語法,線程的語...
      子非魚_t_閱讀 31,705評論 18 399
    • 聲明:轉載請注明出處http://www.lxweimin.com/p/1664dcfd840c 最近在折騰Djan...
      蛇發女妖閱讀 6,289評論 1 10