Flask jinja2 全局函數,宏

內置全局函數

dict()函數,方便生成字典型變量html

{% set user = dict(name='Mike',age=15) %}
<p>{{ user | tojson | safe }}</p>
 
{# 顯示 '{"age": 15, "name": "Mike"}' #}

joiner()函數,神奇的輔助函數。它能夠初始化爲一個分隔符,而後第一次調用時返回空字符串,之後再調用則返回分隔符。對分隔循環中的內容頗有幫助json

{% set sep = joiner("|") %}
{% for val in range(5) %}
    {{ sep() }} <span>{{ val }}</span>
{% endfor %}
 
{# 顯示 "0 | 1 | 2 | 3 | 4" #}

cycler()函數,在給定的序列中輪循,列表項<li>的」class」在」odd」和」even」兩個值間輪循app

{% 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」將其傳入模板便可url

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」全局函數:spa

{% 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」被抽取出來了code

Flask一樣提供了添加全局函數的裝飾器」template_global」,以方便全局函數的添加。咱們來用它將取系統當前時間的函數」current_time」定義爲全局函數。orm

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」全局函數的方法,等同於下面的代碼。htm

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

上例中,程序會按順序尋找模板文件,第一個被找到的模板即被加載,而其後的模板都會被忽略。若是都沒找到,那整個語句都會被忽略。

相關文章
相關標籤/搜索