Flask jinja2 全局函數,宏


內置全局函數

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

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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM