Flask Web Development - Flask 模板1 - 模板機制&Jinja2引擎

來源:互聯網
上載者:User

標籤:style   io   os   使用   ar   java   for   strong   sp   

節選自PartI Chapter3,這個chapter主要講模板工作原理,這裡講的就是Jinja2這個模板,另外還提到了Flask-Bootstrap及Flask-Moment兩個外掛程式,前者對Flask使用Bootstrap做了些封裝,後者對moment.js做了些封裝。內容較多,估計分開搞。

模板存在的意義

可維護性高的代碼是結構良好且整潔的。

當使用者在網站註冊一個賬戶時,他在表單裡填入郵箱跟密碼,並點擊提交按鈕。在server端就收到一個包含這些資料的request,再由Flask分發到相應的視圖函數處理。視圖函數這裡就產生兩個任務,首先在資料庫增加新使用者,然後給使用者的瀏覽器返回一個response。這兩個任務可分別稱為商務邏輯(business logic)和報告邏輯(presentation logic)。

將這兩個邏輯混在一起可能導致代碼混亂,難以維護。可以想象在代碼裡直接產生複雜HTML頁面再嵌入資料的複雜度。將報告邏輯移入模板處理,可以提高應用的可維護性。

模板其實就是一個文本,裡面有一些包含變數的動態部分,這些變數的內容在有request上下文時才能知道。將這些變數替換成實際值,最終產生一個response字串的過程叫渲染。Flask使用強大的Jinja2來處理渲染模板任務。

Jinja2模板引擎

一個簡單的Jinja2模板,index.html

<h1>Hello World!</h1>

就是一個固定的字串,直接返回這個字串。再看稍複雜的, user.html:

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

裡面帶有一個動態部分,name是個變數,response會隨之改變。

渲染模板

Flask預設到應用根目錄下的templates檔案夾下找相應模板,先把上面的兩個簡單模板放到這個檔案夾下,然後修改之前寫的hello.py

from flask import Flask, render_template# ...@app.route(‘/index‘)def index():    return render_template(‘index.html‘)@app.route(‘/user/<name>‘)def user(name):    return render_template(‘user.html‘, name=name)

註:上面是github上的3a tag下代碼

Flask提供的render_template函數可以配合Jinja2使用,它的第一個參數是模板名,之後的參數都是模板中的變數值,以key/value形式傳入。key就是在模板中寫的變數名。

模板中的變數

{{ name }}這種結構表示引用了一個變數,它告訴模板引擎,裡面的值需要在模板被渲染時提供的資料中擷取。

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>

變數可以通過過濾器進一步修改,過濾器放在變數後面以分隔字元隔開。比如下面模板表示變數被首字母大寫化:

Hello, {{ name|capitalize }}

常用過濾器如下:

  • safe 不對傳入值轉義
  • capitalize 傳入值首字母大寫,其他小寫
  • lower 傳入值全部轉為大寫
  • upper 傳入值全部轉為小寫
  • title 傳入值中每個字首大寫
  • trim 傳入值前後空格刪除
  • striptags 傳入值內所有HTML標籤刪除

重點提下safe,出於安全性考慮,Jinja2預設把變數中的值進行轉義,比如值為<h1>Hello</h1>,就會被渲染為&lt;h1&gt;Hello&lt;/h1&gt;,這就導致內嵌標籤失效,如果需要顯示內嵌標籤,就用safe過濾器。

註:對於無法信任的位置,不要使用safe,比如使用者填入的表單值。

更多過濾器可以參考Jinja2官方文檔

控制結構

Jinja2提供了幾種控制結構,來改變模板的渲染流程。下面介紹幾種比較常用的。

模板中加入條件控制:

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

模板中對一個列表元素進行迴圈:

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

Jinja2支援宏,類似於Pyhton代碼裡的函數:

{% 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進來,避免重複書寫:

{% include ‘common.html‘ %}

增加重用性的另一個重要方式,是模板繼承,類似於Python代碼中類的繼承。先定義一個基本模板:

`base.html`:<html><head>    {% block head %}    <title>{% block title %}{% endblock %} - My Application</title>    {% 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()方法可以保留原有內容。

後續會有更多關於模板的真實使用方式。

Flask Web Development - Flask 模板1 - 模板機制&Jinja2引擎

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.