1. 程式人生 > >Flask模板引擎——Jinja2

Flask模板引擎——Jinja2

模板是一個包含響應文字的檔案,其中包含用佔位變量表示的動態部分,其具體指只在請求的上下文中才能知道。使用真是隻替換變數,再返回最終得到的響應字串,這一過程稱為渲染。為了渲染模板,Flask使用了一個名為Jinja2的強大模板引擎。

1. 渲染模板

預設情況下,Flask在程式資料夾中的templates子資料夾中尋找模板。

from flask import Flask, render_template

    app = Flask(__name__)

    @app.route('/')
    def index():
        return render_template('index.html'
) @app.route('/user/<name>') def user(name): return render_template('user.html', name=name)

render_template 函式的第一個引數是模板的檔名(index.html,user.html),隨後的引數都是鍵值對(name=name),表示模板中變數的真實值。

2. 變數

template/user.html:Jinja2模板

<h1>Hello,{{ name }}!<h1>

{{ name }}結構表示一個變數,告訴模板引擎這個位置的值從渲染模板時使用的資料中獲取。
可以使用過濾器修改變數,過濾器名稱新增在變數名之後,中間使用豎線分割。

Hello,{{ name|capitalize }}

Jinja2變數過濾器:
safe: 渲染時不轉義
capitalize:把值的首字母轉換成大寫,其他字母轉換成小寫
lower: 把值轉換成小寫形式
upper: 把值轉換成大寫形式
title: 把值中每個單詞的首字母都轉換成大寫
trim: 把值的首尾空格都去掉
striptags: 渲染之前把值中所有的HTML標籤都刪掉

3.控制結構

if迴圈

例:

{%if user %}
    Hello, {{ user }}
! {% else %} Hello, Stranger! {% endif %}

for迴圈

<ul>
    {% for comment in comments %}
        <li>{{ comment }}<li>
    {% endfor %}
</ul>

巨集

巨集類似於函式。需要在多處重複使用的模板程式碼片段可以寫入單獨的檔案,再包含在所有模板中,以避免重複。另一種重複使用程式碼的強大方式是模板繼承。
例:
首先建立一個名為base.html的基模板。

<html>
<head>
    {% block head %}
    <title>{% block title %}{% endblock %} - My Application</titel>
    {% endblock %}
</head>
<body>
    {% block body %}{% endblock %}
</body>
<html>

由block標籤定義的元素可以在衍生模板中修改。head,title,body,注意title包含在head中
下面示例是基模板的衍生模板。

{% extends "base.html" %}{% block title %}index{% endblock %}{% block head %}{{ super }}
    <style></style>
{% endblock %}{% block body %}
<h1>Hello, World!</h1>
{% endblock %}

extends指令宣告這個模板衍生自base.html。基模板中的三個塊被重新定義,模板引擎會將其插入適當的位置。**注意新定義的head塊,在基模板中其內容不是空的,所以使用super()獲取原來的內容。

4.自定義錯誤頁面

最常見的錯誤程式碼有兩個:404,客戶端請求未知頁面或路由時顯示;500,有未處理的異常時顯示。
示例:自定義錯誤頁面

@app.errorhandler(404)
def page_not_found(e):
    return render_template('404.html'), 404


@app.errorhandler(500)
def internal_server_error(e):
    return render_template('500.html'), 500

錯誤處理程式中引用的模板也需要編寫。這些模板應該和常規頁面使用相同的佈局,因此要有一個導航條和顯示錯誤訊息的頁面頭部。
Flask-Bootstrap提供了一個具有頁面基本佈局的基模板。
示例:

{% extends "bootstrap/base.html" %}{% block title %}Flasky{% endblock %}{% block navbar %}
<div class="navbar navbar-inverse" role="navigation">
    <div class="container">
        <div class="navbar-header">
            <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="/">Flasky</a>
        </div>
        <div class="navbar-collapse collapse">
            <ul class="nav navbar-nav">
                <li><a href="/">Home</a></li>
            </ul>
        </div>
    </div>
</div>
{% endblock %}{% block content %}
<div class="container">
    {% block page_content %}{% endblock %}
</div>
{% endblock %}

這是一個繼承自bootstrap/base.html的新模板,其中定義了導航條。content塊中只有個div容器,其中包含了一個名為page_content的新的空塊,塊中的內容由衍生模板定義。
通過繼承base.html模板寫404.html。示例:

{% extends "base.html" %}{% block title %}Flasky - Page Not Found{% endblock %}{% block page_content %}
<div class="page-header">
    <h1>Not Found</h1>
</div>
{% endblock %}

505.html:

{% extends "base.html" %}{% block title %}Flasky - Internal Server Error{% endblock %}{% block page_content %}
<div class="page-header">
    <h1>Internal Server Error</h1>
</div>
{% endblock %}

user.html:

{% extends "base.html" %}{% block title %}Flasky{% endblock %}{% block page_content %}
<div class="page-header">
    <h1>Hello, {{ name }}!</h1>
</div>
{% endblock %}

5.連結

Flask提供了url_for()輔助函式,它可以使用程式URL對映中儲存的資訊生成URL。
使用url_for()生成動態地址時,將動態部分作為關鍵字引數傳入。例如:url_for(‘user’, name = ‘john’, _external = True)的返回結果時http://localhost:5000/user/john.
傳入url_for()的關鍵字引數不僅限於動態路由中的引數。函式能將任何額為引數新增到查詢字元中。

6.靜態檔案

預設設定下,Flask在程式根目錄中名為static的子目錄中尋找靜態檔案。
示例展示瞭如何在程式的基模板中放置favicon.ico圖示(此圖示就是Flask的logo)。這個圖示會顯示在瀏覽器的位址列中。
示例:

...
{% block head %}
{{ super() }}
<link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
<link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x-icon">
{% endblock %}
...

圖示的宣告會插入head塊的末尾。使用super()保留基模板中定義的塊的原始內容。

7.使用Flask-Moment本地化日期和時間

Flask-Moments時一個Flask擴充套件,用於把moment.js整合到jinjia2模板中。
引入moment.js庫(在base.html模板底部):

...
{% block scripts %}
{{ super() }}
{{ moment.include_moment() }}
{% endblock %}

在hello.py中加入一個datetime變數:

...
from datetime import datetime
...
moment = Moment(app)
...
@app.route('/')
def index():
    return render_template('index.html',
                           current_time=datetime.utcnow())

使用Flask-Moment渲染時間戳(在index.html中加入):

...
<p>The local date and time is {{ moment(current_time).format('LLL') }}.</p>
<p>That was {{ moment(current_time).fromNow(refresh=True) }}.</p>