Flask: 模版

引言

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

Jinja2 模版引擎

形式最簡單的Jinja2模版就是一個包含響應文本的文件。

示例 1 templates/index.html

<h1>Hello World!</h1>

示例 2 templates/user.html

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

示例2 中包含一個使用變量表示的動態部分 {{ name }}

渲染模版

默認情況下, Flask 在程序文件夾中的 templates 子文件夾中尋找模版。我們將 示例1 和 示例2 分別命名爲 index.htmluser.html 存放在 templates 文件夾下。

視圖函數對應爲:

from flask import Flask, render_template

#...

@app.route('/')
def index():
    return render_template('index.html')

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

Flask 提供的 render_template 函數把 Jinja2 模版引擎集成到程序中。 render_template 函數的第一個參數是模版的文件名。隨後的參數都是鍵值對, 表示模版中變量對應的真實值。在這段代碼中,第二個模版收到一個名爲 name 的變量。

視圖函數中 name=name 是關鍵字參數,左邊的 name 表示參數名,就是模版中的佔位符;右邊的 name 是當前作用域中的變量,表示同名參數的值。

變量

示例2 在模版中使用的 {{ name }} 結構表示一個變量,它是一種特殊的佔位符, 告訴模版引擎這個位置的值從渲染模版時使用的數據中獲取。

Jinja2 能識別所有類型的變量,甚至 列表、字典和對象。在模版中使用變量的一些示例如下:

<p>A vakue from a dictionary: {{ mydict['key'] }}.</p>
<p>A vakue from a list: {{ mylist[3] }}.</p>
<p>A vakue from a list, with a variable index: {{ mylist[myintvar] }}.</p>
<p>A vakue from a object's method: {{ myobj.somemethod() }}.</p>

可以使用 過濾器 修改變量, 過濾器名添加在變量名之後, 中間使用豎線分隔。例如,下述模版以首字母大寫形式顯示變量 name 值:

Hello, {{ name|capitalize }}

常用過濾器:

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

注意:千萬別在不可信的值上使用 safe 過濾器,例如用戶在表單中輸入的文本。
默認情況下,出於安全考慮, Jinja2 會轉移所有變量。例如, 如果一個變量的值爲 '<h1>Hello</h1>'Jinja2 會將其渲染成 '&lt;h1&gt;Hello&lt;/h1&gt;',瀏覽器能顯示 h1 元素,但不會進行解釋。

控制結構

Jinja2 提供了多種控制結構,可用來改變模版的渲染流程。

條件控制語句

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

for 循環

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

宏類似 python 中的函數

{% macro render_comment(comment) %}
    <li>{{ comment }}</li>
{% endmacro %}

<ul>
    {% for comment in comments %}
        {{ render_comment(comment) }}
    {% endfor %}
</ul>

包含

需要在多出重複使用的模版代碼片段可以寫入單獨的文件,再包含在所有模塊中,以避免重複:

{% include 'common.html' %}

繼承

另一種重複使用代碼的強大方式是模版集成,它類似與 Python 代碼中的類繼承。首先, 創建一個名爲 base.html 的基模版:

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

block 標籤定義的元素可在衍生模版中修改。在 base.html 中,我們定義了名爲 headtitlebody 的塊。注意, title 包含在 head 中。 下面這個示例是基模版的衍生模版:

{% extends "base.html" %}
{% block title %}Index{% endblock %}
{% block head %}
    {{ supper() }}
    <style>
    </style>
{% endblock %}
{% block body %}
<h1>Hello, World!</h1>
{% endblock %}

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章