內置全局函數
dict()函數,方便生成字典型變量
{% set user = dict(name='Mike',age=15) %} <p>{{ user | tojson | safe }}</p> {# 顯示 '{"age": 15, "name": "Mike"}' #}
joiner()函數,神奇的輔助函數。它可以初始化為一個分隔符,然后第一次調用時返回空字符串,以后再調用則返回分隔符。對分隔循環中的內容很有幫助
{% set sep = joiner("|") %} {% for val in range(5) %} {{ sep() }} <span>{{ val }}</span> {% endfor %} {# 顯示 "0 | 1 | 2 | 3 | 4" #}
cycler()函數,在給定的序列中輪循,列表項<li>的”class”在”odd”和”even”兩個值間輪循
{% set cycle = cycler('odd', 'even') %} <ul> {% for num in range(10, 20, 2) %} <li class="{{ cycle.next() }}">Number is "{{ num }}", next line is "{{ cycle.current }}" line.</li> {% endfor %} </ul>
“cycler()”函數返回的對象可以做如下操作
- next(),返回當前值,並往下一個值輪循
- reset(),重置為第一個值
- current,當前輪循到的值
自定義全局函數
將Flask應用代碼中定義的函數,通過”add_template_global”將其傳入模板即可
import re def accept_pattern(pattern_str): pattern = re.compile(pattern_str, re.S) def search(content): return pattern.findall(content) return dict(search=search, current_pattern=pattern_str) app.add_template_global(accept_pattern, 'accept_pattern')
上例中的accept_pattern函數會先預編譯一個正則,然后返回的字典中包含一個查詢函數”search”,之后調用”search”函數就可以用編譯好的正則來搜索內容了。”app.add_template_global”方法的第一個參數是自定義的全局函數,第二個是全局函數名稱。現在,讓我們在模板中使用”accept_pattern”全局函數:
{% with pattern = accept_pattern("<li>(.*?)</li>") %} {% set founds = pattern.search("<li>Tom</li><li>Bob</li>") %} <ul> {% for item in founds %} <li>Found: {{ item }}</li> {% endfor %} </ul> <p>Current Pattern: {{ pattern.current_pattern }}</p> {% endwith %}
“Tom”和”Bob”被抽取出來了
Flask同樣提供了添加全局函數的裝飾器”template_global”,以方便全局函數的添加。我們來用它將取系統當前時間的函數”current_time”定義為全局函數。
import time @app.template_global('end_with') def current_time(timeFormat="%b %d, %Y - %H:%M:%S"): return time.strftime(timeFormat)
<p>Current Time is: {{ current_time() }}</p> <p>Current Day is: {{ current_time("%Y-%m-%d") }}</p>
Flask添加全局函數的方法是封裝了對Jinja2環境變量的操作。上述添加”current_time”全局函數的方法,等同於下面的代碼。
app.jinja_env.globals['current_time'] = current_time
宏 (Macro)
{% macro input(name, type='text', value='') -%} <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}"> {%- endmacro %}
<p>{{ input('username', value='user') }}</p> <p>{{ input('password', 'password') }}</p> <p>{{ input('submit', 'submit', 'Submit') }}</p>
訪問調用者內容
先來創建個宏”list_users”:
{% macro list_users(users) -%} <table> <tr><th>Name</th><th>Action</th></tr> {%- for user in users %} <tr><td>{{ user.name |e }}</td>{{ caller() }}</tr> {%- endfor %} </table> {%- endmacro %}
調用者的代碼:
{% set users=[{'name':'Tom','gender':'M','age':20}, {'name':'John','gender':'M','age':18}, {'name':'Mary','gender':'F','age':24}] %} {% call list_users(users) %} <td><input name="delete" type="button" value="Delete"></td> {% endcall %}
與上例不同,這里我們使用了”{% call %}”語句塊來調用宏,語句塊中包括了一段生成”Delete”按鈕的代碼。運行下試試,你會發現每個用戶名后面都出現了”Delete”按鈕,也就是”{{ caller( ) }}”部分被調用者”{% call %}”語句塊內部的內容替代了,個人覺得,主要是有些時候HTML語句太復雜(如上例),不方便寫在調用參數上,所以就寫在”{% call %}”語句塊里了。
Jinja2的宏不但能訪問調用者語句塊的內容,還能給調用者傳遞參數
首先,我們將表格增加一列性別,並在宏里調用”caller()”方法時,傳入一個變量”user.gender”:
{% macro list_users(users) -%} <table> <tr><th>Name</th><th>Gender</th><th>Action</th></tr> {%- for user in users %} <tr><td>{{ user.name |e }}</td>{{ caller(user.gender) }}</tr> {%- endfor %} </table> {%- endmacro %}
修改下調用者語句塊:
{% call(gender) list_users(users) %} <td> {% if gender == 'M' %} <img src="{{ url_for('static', filename='img/male.png') }}" width="20px"> {% else %} <img src="{{ url_for('static', filename='img/female.png') }}" width="20px"> {% endif %} </td> <td><input name="delete" type="button" value="Delete"></td> {% endcall %}
我們在使用”{% call %}”語句時,將其改為了”{% call(gender) … %}”,這個括號中的”gender”就是用來接受宏里傳來的”user.gender”變量。因此我們就可以在”{% call %}”語句中使用這個”gender”變量來判斷用戶性別。這樣宏就成功地向調用者傳遞了參數。
宏的內部變量
宏的內部可以使用”caller( )”方法獲取調用者的內容。此外宏還提供了兩個內部變量:
varargs
這是一個列表。如果調用宏時傳入的參數多於宏聲明時的參數,多出來的沒指定參數名的參數就會保存在這個列表中。
kwargs
這是一個字典。如果調用宏時傳入的參數多於宏聲明時的參數,多出來的指定了參數名的參數就會保存在這個字典中。
{% macro input(name, type='text', value='') -%} <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}"> <br /> {{ varargs }} <br /> {{ kwargs }} {%- endmacro %} <p>{{ input('submit', 'submit', 'Submit', 'more arg1', 'more arg2', ext='more arg3') }}</p>
可以看到,varargs變量存了參數列表”[‘more arg1’, ‘more arg2’]”,而kwargs字典存了參數”{‘ext’:’more arg3′}”。
當”include”的模板文件不存在時,程序會拋出異常。你可以加上”ignore missing”關鍵字,這樣如果模板不存在,就會忽略這段”{% include %}”語句。
{% include 'footer.html' ignore missing %}
{% include ['footer.html','bottom.html','end.html'] ignore missing %}
上例中,程序會按順序尋找模板文件,第一個被找到的模板即被加載,而其后的模板都會被忽略。如果都沒找到,那整個語句都會被忽略。