Jinja2 模板的學習

默認情況下啄清,F(xiàn)lask 在程序文件夾中的 templates 子文件夾中尋找模板空免。在下一個 hello.py 版本中,要把前面定義的模板保存在 templates 文件夾中款筑,并分別命名為 index.html 和 user.html腋么。

index.thm的代碼如下,不傳參數(shù)

<html>
    <head>
        <title>歡迎來到王者榮耀</title> 
    </head>
    <body>
        <p>你是不是要成為一個高手</p>
    </body>

</html>

user.html中傳遞一個參數(shù)

<html>
    <head>
        <title>歡迎來到王者榮耀</title> 
    </head>
    <body>
        <p>你是不是要成為一個高手咕娄,你的名字是{{name}}</p>
    </body>

</html>

在hello.py中,

from flask import render_template
@app.route('/')
def index():
    return render_template('index.html')
@app.route('/user/<name>') #尖括號中的動態(tài)名字
def user(name):
    return render_template('user.html',name=name)

1珊擂、變量

在模板中使用的 {{ name }} 結(jié)構(gòu)表示一個變量圣勒,它是一種特殊的占位符,告訴模
板引擎這個位置的值從渲染模板時使用的數(shù)據(jù)中獲取摧扇。
Jinja2 能識別所有類型的變量圣贸,甚至是一些復雜的類型,例如列表扳剿、字典和對象旁趟。在模板 中使用變量的一些示例如下:

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

可以使用過濾器修改變量昼激,過濾器名添加在變量名之后庇绽,中間使用豎線分隔锡搜。例如,下述 模板以首字母大寫形式顯示變量 name 的值:

Hello, {{ name|capitalize }}

下面是常用的過濾器

8568F68D-6315-4E2D-88A3-205D6C011941.png

更多的fliter官方文檔

2瞧掺、Jinja2的控制結(jié)構(gòu)

if - else 的寫法

    {% if name %}
        Hello,{{name}}
    {% else %}
        Hello ,你沒名字一看就是菜啊!!!
    {% endif %}

for 循環(huán)

    {% for title in ["黃金4","黃金3","黃金2"] %}
        <li>{{title}}</li>
    {% endfor %}

Jinja2 還支持宏耕餐。宏類似于 Python 代碼中的函數(shù)。例如:

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

為了重復使用宏辟狈,我們可以將其保存在單獨的文件中肠缔,然后在需要使用的模板中導入:

{% import 'macros.html' as macros %}
 <ul>
    {% for comment in comments %}
    {{ macros.render_comment(comment) }}
    {% endfor %} 
</ul>

需要在多處重復使用的模板代碼片段可以寫入單獨的文件,再包含在所有模板中哼转,以避免 重復:

{% include 'common.html' %}

另一種重復使用代碼的強大方式是模板繼承明未,它類似于 Python 代碼中的類繼承。首先壹蔓,創(chuàng)
建一個名為 base.html 的基模板:

<html>
    <head>
        {% block head %}
        <title>{% block title %}{% endblock %} - MyApplication</title>
        {% endblock %}
    </head>
    <body>
        {%block body %}
        <p>我是來自基類</p>
        {%endblock %}
    </body>

</html>

新建一個son.html 繼承base.html

{% extends "base.html" %}
{% block title %} INDEX {% endblock %}
{% block head %}
    {{super()}}
{% endblock %}
{% block body %}
{{super()}}
<h1>我也是醉了趟妥,這是啥基礎(chǔ)自基礎(chǔ)模板</h1>
{% endblock %}

extends 指令聲明這個模板衍生自 base.html。在 extends 指令之后佣蓉,基模板中的 3 個塊被 重新定義披摄,模板引擎會將其插入適當?shù)奈恢谩W⒁庑露x的 head 塊勇凭,在基模板中其內(nèi)容不 是空的疚膊,所以使用 super() 獲取原來的內(nèi)容。

3虾标、自定義錯誤頁面的方式

自定義錯誤頁面
     @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

4寓盗、鏈接

任何具有多個路由的程序都需要可以連接不同頁面的鏈接,例如導航條璧函。
在模板中直接編寫簡單路由的 URL 鏈接不難贞让,但對于包含可變部分的動態(tài)路由,在模板 中構(gòu)建正確的 URL 就很困難柳譬。而且喳张,直接編寫 URL 會對代碼中定義的路由產(chǎn)生不必要的 依賴關(guān)系。如果重新定義路由美澳,模板中的鏈接可能會失效销部。
為了避免這些問題,F(xiàn)lask 提供了 url_for() 輔助函數(shù)制跟,它可以使用程序 URL 映射中保存 的信息生成 URL舅桩。
url_for() 函數(shù)最簡單的用法是以視圖函數(shù)名(或者 app.add_url_route() 定義路由時使用 的端點名)作為參數(shù),返回對應的 URL雨膨。例如擂涛,在當前版本的 hello.py程序中調(diào)用 url_ for('index')得到的結(jié)果是/。調(diào)用url_for('index', _external=True)返回的則是絕對地 址聊记,在這個示例中是 http://localhost:5000/撒妈。
生成連接程序內(nèi)不同路由的鏈接時恢暖,使用相對地址就足夠了。如果要生成在 瀏覽器之外使用的鏈接狰右,則必須使用絕對地址杰捂,例如在電子郵件中發(fā)送的 鏈接。
使用 url_for() 生成動態(tài)地址時棋蚌,將動態(tài)部分作為關(guān)鍵字參數(shù)傳入嫁佳。例如,url_for ('user', name='john', _external=True) 的返回結(jié)果是 http://localhost:5000/user/john谷暮。
傳入 url_for() 的關(guān)鍵字參數(shù)不僅限于動態(tài)路由中的參數(shù)蒿往。函數(shù)能將任何額外參數(shù)添加到 查詢字符串中。例如湿弦,url_for('index', page=2) 的返回結(jié)果是 /?page=2熄浓。

5、靜態(tài)文件

Web 程序不是僅由 Python 代碼和模板組成省撑。大多數(shù)程序還會使用靜態(tài)文件赌蔑,例如 HTML
代碼中引用的圖片、JavaScript 源碼文件和 CSS竟秫。
例如娃惯,調(diào)用 url_for('static', filename='css/styles.css', _external=True) 得 到 的 結(jié) 果 是 http:// localhost:5000/static/css/styles.css。
默認設(shè)置下肥败,F(xiàn)lask 在程序根目錄中名為 static 的子目錄中尋找靜態(tài)文件趾浅。如果需要,可在 static 文件夾中使用子文件夾存放文件馒稍。服務器收到前面那個 URL 后皿哨,會生成一個響應, 包含文件系統(tǒng)中 static/css/styles.css 文件的內(nèi)容纽谒。

6证膨、使用Flask-Moment本地化日期和時間

有一個使用 JavaScript 開發(fā)的優(yōu)秀客戶端開源代碼庫,名為 moment.js(http://momentjs. com/)鼓黔,它可以在瀏覽器中渲染日期和時間央勒。Flask-Moment 是一個 Flask 程序擴展,能把 moment.js 集成到 Jinja2 模板中澳化。Flask-Moment 可以使用 pip 安裝:

 pip3 install flask-moment

這個擴展的初始化方法如示例 3-11 所示崔步。 示例 3-11 hello.py:初始化 Flask-Moment

from flask.ext.moment import Moment moment = Moment(app)

7、使用Flask-Bootstrap集成Twitter Bootstrap

安裝

 pip3 install flask-bootstrap

初始化 Flask-Bootstrap

from flask_bootstrap import Bootstrap
bootstrap = Bootstrap(app)

新建一個home.html模板缎谷,繼承bootstrap的base.html模板

{% 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">
         <div class="page-header">
             <h1>Hello, {{ name }}!</h1>
         </div>
     </div>
{% endblock %}

Flask-Bootstrap 的 base.html 模板還定義了很多其他塊井濒,都可在衍生模板中使用。表 3-2 列

![Uploading 18C6212F-F78C-4AA2-8281-9FAB2C5FC341_474250.png . . .]
18C6212F-F78C-4AA2-8281-9FAB2C5FC341.png

上圖中很多塊都是 Flask-Bootstrap 自用的,如果直接重定義可能會導致一些問題瑞你。例 如酪惭,Bootstrap 所需的文件在 styles 和 scripts 塊中聲明。如果程序需要向已經(jīng)有內(nèi)容的塊 中添加新內(nèi)容捏悬,必須使用 Jinja2 提供的 super() 函數(shù)撞蚕。例如润梯,如果要在衍生模板中添加新 的 JavaScript 文件过牙,需要這么定義 scripts 塊:

{% block scripts %}
{{ super() }}
<script type="text/javascript" src="my-script.js"></script> 
{% endblock %}

7、web表單

盡管 Flask 的請求對象提供的信息足夠用于處理 Web 表單纺铭,但有些任務很單調(diào)寇钉,而且要重 復操作。比如舶赔,生成表單的 HTML 代碼和驗證提交的表單數(shù)據(jù)扫倡。
Flask-WTF(http://pythonhosted.org/Flask-WTF/)擴展可以把處理 Web 表單的過程變成一 種愉悅的體驗。這個擴展對獨立的 WTForms(http://wtforms.simplecodes.com)包進行了包 裝竟纳,方便集成到 Flask 程序中撵溃。
Flask-WTF 及其依賴可使用 pip 安裝:

pip3 install flask-wtf

默認情況下,F(xiàn)lask-WTF能保護所有表單免受跨站請求偽造(Cross-Site Request Forgery锥累,
CSRF)的攻擊缘挑。惡意網(wǎng)站把請求發(fā)送到被攻擊者已登錄的其他網(wǎng)站時就會引發(fā) CSRF 攻擊。 為了實現(xiàn) CSRF 保護桶略,F(xiàn)lask-WTF 需要程序設(shè)置一個密鑰语淘。Flask-WTF 使用這個密鑰生成
加密令牌,再用令牌驗證請求中表單數(shù)據(jù)的真?zhèn)渭始摺TO(shè)置密鑰的方法設(shè)置 Flask-WTF

app = Flask(__name__)
app.config['SECRET_KEY'] = 'hard to guess string'
   33

app.config 字典可用來存儲框架惶翻、擴展和程序本身的配置變量。使用標準的字典句法就能 把配置值添加到 app.config 對象中鹅心。這個對象還提供了一些方法吕粗,可以從文件或環(huán)境中導 入配置值。
SECRET_KEY 配置變量是通用密鑰旭愧,可在 Flask 和多個第三方擴展中使用溯泣。如其名所示,加 密的強度取決于變量值的機密程度榕茧。不同的程序要使用不同的密鑰垃沦,而且要保證其他人不 知道你所用的字符串。

表單類:
使用 Flask-WTF 時用押,每個 Web 表單都由一個繼承自 Form 的類表示肢簿。這個類定義表單中的 一組字段,每個字段都用對象表示。字段對象可附屬一個或多個驗證函數(shù)池充。驗證函數(shù)用來 驗證用戶提交的輸入值是否符合要求桩引。
下面是一個簡單的 Web 表單,包含一個文本字段和一個提交按鈕收夸。

from flask_wtf import Form
from wtforms import StringField, SubmitField 
from wtforms.validators import Required
class NameForm(Form):
    name = StringField('What is your name?', validators=[Required()]) 
    submit = SubmitField('Submit')

這個表單中的字段都定義為類變量坑匠,類變量的值是相應字段類型的對象。在這個示例中卧惜, NameForm 表單中有一個名為 name 的文本字段和一個名為 submit 的提交按鈕厘灼。StringField 類表示屬性為 type="text" 的 <input> 元素。SubmitField 類表示屬性為 type="submit" 的 <input> 元素咽瓷。字段構(gòu)造函數(shù)的第一個參數(shù)是把表單渲染成 HTML 時使用的標號设凹。
StringField 構(gòu)造函數(shù)中的可選參數(shù) validators 指定一個由驗證函數(shù)組成的列表,在接受 用戶提交的數(shù)據(jù)之前驗證數(shù)據(jù)茅姜。驗證函數(shù) Required() 確保提交的字段不為空闪朱。

WTForms 支持的 HTML 標準字段如下圖

9278B3CA-AF23-4D0D-82F1-069F17A27188.png

WTForms 內(nèi)建的驗證函數(shù)

3A0C9B81-7C18-404B-AC94-6E71EDE4FEE5.png

把表單類渲染為HTML
例通過參數(shù) form 傳入模板,在模板中可以生成一個簡單的表單钻洒,如下所示:

     <form method="POST">
         {{ form.hidden_tag() }}
         {{ form.name.label }} {{ form.name() }}
         {{ form.submit() }}
    </form>

即便能指定 HTML 屬性奋姿,但按照這種方式渲染表單的工作量還是很大,所以在條件允許的 情況下最好能使用 Bootstrap 中的表單樣式素标。Flask-Bootstrap 提供了一個非常高端的輔助函 數(shù)称诗,可以使用 Bootstrap 中預先定義好的表單樣式渲染整個 Flask-WTF 表單,而這些操作 只需一次調(diào)用即可完成糯钙。使用 Flask-Bootstrap粪狼,上述表單可使用下面的方式渲染:

{% import "bootstrap/wtf.html" as wtf %}
 {{ wtf.quick_form(form) }}

Flash消息
請求完成后,有時需要讓用戶知道狀態(tài)發(fā)生了變化任岸。這里可以使用確認消息再榄、警告或者錯 誤提醒。一個典型例子是享潜,用戶提交了有一項錯誤的登錄表單后困鸥,服務器發(fā)回的響應重新 渲染了登錄表單,并在表單上面顯示一個消息剑按,提示用戶用戶名或密碼錯誤疾就。
這種功能是 Flask 的核心特性。

@app.route('/',methods = ['GET','POST'])
def index():
    name = None
    form = NameForm()
    if form.validate_on_submit():
        
        old_name = session.get('name')
        new_name = form.name.data
        session['name'] = new_name
        if old_name is not None and old_name != new_name:
            flash('你似乎改變了你的名字')
        return redirect(url_for('index'))
        
    return render_template('testForm.html', form=form, name=session.get('name'))

在這個示例中艺蝴,每次提交的名字都會和存儲在用戶會話中的名字進行比較猬腰,而會話中存儲 的名字是前一次在這個表單中提交的數(shù)據(jù)。如果兩個名字不一樣猜敢,就會調(diào)用 flash() 函數(shù)姑荷, 在發(fā)給客戶端的下一個響應中顯示一個消息盒延。

獲取get_flashed_messages()來獲取消息
在html中顯示消息

{% for message in get_flashed_messages() %}
        <div class="alert alert-waring">
            <button type="button" class="close" data-dismiss="alert">&times;</button>
            {{message}}
        </div>
{% endfor %}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市鼠冕,隨后出現(xiàn)的幾起案子添寺,更是在濱河造成了極大的恐慌,老刑警劉巖懈费,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件计露,死亡現(xiàn)場離奇詭異,居然都是意外死亡憎乙,警方通過查閱死者的電腦和手機票罐,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寨闹,“玉大人胶坠,你說我怎么就攤上這事君账》北ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵乡数,是天一觀的道長椭蹄。 經(jīng)常有香客問我,道長净赴,這世上最難降的妖魔是什么绳矩? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮玖翅,結(jié)果婚禮上翼馆,老公的妹妹穿的比我還像新娘。我一直安慰自己金度,他們只是感情好应媚,可當我...
    茶點故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著猜极,像睡著了一般中姜。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上跟伏,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天丢胚,我揣著相機與錄音,去河邊找鬼受扳。 笑死携龟,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的勘高。 我是一名探鬼主播峡蟋,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼浮定,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了层亿?” 一聲冷哼從身側(cè)響起桦卒,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎匿又,沒想到半個月后方灾,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨居荒郊野嶺守林人離奇死亡碌更,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年裕偿,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片痛单。...
    茶點故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡嘿棘,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出旭绒,到底是詐尸還是另有隱情鸟妙,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布挥吵,位于F島的核電站重父,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏忽匈。R本人自食惡果不足惜房午,卻給世界環(huán)境...
    茶點故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望丹允。 院中可真熱鬧郭厌,春花似錦、人聲如沸雕蔽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽萎羔。三九已至液走,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間贾陷,已是汗流浹背缘眶。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留髓废,地道東北人巷懈。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓,卻偏偏與公主長得像慌洪,于是被迫代替她去往敵國和親顶燕。 傳聞我的和親對象是個殘疾皇子凑保,可洞房花燭夜當晚...
    茶點故事閱讀 44,647評論 2 354

推薦閱讀更多精彩內(nèi)容

  • 22年12月更新:個人網(wǎng)站關(guān)停,如果仍舊對舊教程有興趣參考 Github 的markdown內(nèi)容[https://...
    tangyefei閱讀 35,180評論 22 257
  • 第三章 模板 序 為什么要分離 易于維護的代碼涌攻,關(guān)鍵在于保持簡單的結(jié)構(gòu)欧引。而我們之前編寫的hello.py雖然簡單,...
    科幻經(jīng)典閱讀 1,533評論 0 6
  • 第4章 Web表單 我們在第二章介紹過請求對象恳谎,它包含有客戶端請求的全部信息芝此。尤其是,可以通過request.fo...
    易木成華閱讀 1,025評論 0 1
  • 請求對象包含客戶端發(fā)出的所有請求信息因痛。其中 request.form 能獲取 POST 請求中提交的表單數(shù)據(jù)婚苹。 我...
    焉知非魚閱讀 1,132評論 0 2
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn)鸵膏,斷路器膊升,智...
    卡卡羅2017閱讀 134,652評論 18 139