天天看點

在Flask中使用Jinja2進行模闆制作:基礎知識

Jinja2是用純Python編寫的模闆引擎。 它提供了受Django啟發的非XML文法,但支援内聯表達式和可選的沙盒環境。 除了是易于使用的獨立模闆引擎之外,它很小但是很快。 Flask是基于Python的微型Web架構,可讓您快速有效地編寫Web應用程式。

在這個由三部分組成的系列文章中,我将從Flask的角度開始介紹Jinja2的基礎模闆。 在本系列的後續部分中,我将介紹進階模闆主題,同時學習如何在子產品化和可擴充設計的基于Flask的應用程式中布局模闆。

我假設您對使用Flask和環境設定最佳實踐有基本的了解,并在開發Python應用程式時遵循使用virtualenv 。

安裝套件

Flask随Jinja2一起打包,是以我們隻需要安裝Flask。 對于本系列,我建議使用Flask的開發版本,該版本包括許多其他功能中的更穩定的指令行支援以及對Flask的總體改進。

pip install https://github.com/mitsuhiko/flask/tarball/master
           

需要模闆引擎嗎?

在Flask中,我們可以編寫完整的Web應用程式,而無需任何第三方模闆引擎。 讓我們看看下面的一個小型

Hello World

應用程式:

from flask import Flask

app = Flask(__name__)

@app.route('/')
@app.route('/hello')
@app.route('/hello/<user>')
def hello_world(user=None):
    user = user or 'Shalabh'
    return '''
    <html>
        <head>
            <title>Templating in Flask</title>
        </head>
        <body>
            <h1>Hello %s!</h1>
            <p>Welcome to the world of Flask!</p>
        </body>
    </html>''' % user
       
if __name__ == '__main__':
    app.run()
           

顯然,在HTML,CSS和JS代碼成千上萬行的真實Web應用程式中,上述編寫應用程式的模式是不可行的。 在這裡,模闆可以節省我們的時間,因為我們可以通過使模闆分開來構造視圖代碼。 Flask預設情況下提供對Jinja2的支援,但也可以使用任何其他模闆引擎。

布置模闆

預設情況下,Flask希望将模闆放置在應用程式根級别的名為

templates

的檔案夾中。 然後Flask通過使該檔案夾可用于

render_template()

方法來自動讀取内容。 我将通過重組上面顯示的瑣碎的

Hello World

應用程式來示範相同的内容。

應用程式結構如下所示。

flask_app/
    my_app.py    
    templates/
        - index.html
           

應用本身

flask_app / my_app.py

from flask import Flask, render_template, request

app = Flask(__name__)

@app.route('/')
@app.route('/hello')
@app.route('/hello/<user>')
def hello_world(user=None):
    user = user or 'Shalabh'
    return render_template('index.html', user=user)
           

flask_app / templates / index.html

<html>
  <head>
    <title>Templating in Flask</title>
  </head>
  <body>
    <h1>Hello {{ user }}!</h1>
    <p>Welcome to the world of Flask!</p>
  </body>
</html>
           

要運作該應用程式,隻需在指令行上執行以下指令:

flask --app=my_app run
           

在浏覽器中打開http://127.0.0.1:5000/以檢視實際應用程式。 如果使用http://127.0.0.1:5000/hello ,結果也将相同。

在Flask中使用Jinja2進行模闆制作:基礎知識

嘗試打開以您的名字作為最後一部分的URL。 是以,如果您的名字叫John,則URL為http://127.0.0.1:5000/hello/John 。 現在頁面看起來像這樣:

在Flask中使用Jinja2進行模闆制作:基礎知識

很簡單,在

hello_world

方法中,從請求中擷取

hello

之後的URL的最後一部分,然後傳遞給使用

render_template()

呈現的模闆的上下文。 然後,使用Jinja2占位符

{{ user }}

從模闆上下文中解析此值。 此占位符根據模闆上下文評估放置在其中的所有表達式。

了解模闆中的塊和繼承

通常,任何Web應用程式都會有許多彼此不同的網頁。 整個站點中幾乎所有頁面中的頁眉和頁腳等代碼塊都相同。 同樣,菜單也保持不變。 實際上,通常隻是中心容器塊發生變化,其餘的通常保持不變。 為此,Jinja2提供了一種在模闆之間進行繼承的好方法。 擁有一個基礎模闆是一個好習慣,我們可以在該模闆中建構網站的基本布局以及頁眉和頁腳。

我将建立一個小應用程式來展示不同類别的産品清單。 對于樣式,我将使用Bootstrap架構對模闆進行基本設計。 現在,應用程式結構如下所示。

flask_app/
    my_app.py    
    templates/
        - base.html
        - home.html
        - product.html
    static/
        css/
            - bootstrap.min.css
            - main.css
        js/
            - bootstrap.min.js
           

在這裡,可以從上述引導網站下載下傳

static/css/bootstrap.min.css

static/js/bootstrap.min.js

。 其餘的應用程式代碼如下所示。

flask_app / my_app.py

from flask import Flask, render_template, abort

app = Flask(__name__)

PRODUCTS = {
    'iphone': {
        'name': 'iPhone 5S',
        'category': 'Phones',
        'price': 699,
    },
    'galaxy': {
        'name': 'Samsung Galaxy 5',
        'category': 'Phones',
        'price': 649,
    },
    'ipad-air': {
        'name': 'iPad Air',
        'category': 'Tablets',
        'price': 649,
    },
    'ipad-mini': {
        'name': 'iPad Mini',
        'category': 'Tablets',
        'price': 549
    }
}

@app.route('/')
@app.route('/home')
def home():
    return render_template('home.html', products=PRODUCTS)

@app.route('/product/<key>')
def product(key):
    product = PRODUCTS.get(key)
    if not product:
        abort(404)
    return render_template('product.html', product=product)
           

在此檔案中,我已對産品清單進行了寫死,以使應用程式更簡單,并且僅關注模闆部分。 我建立了兩個端點

home

product

,前者用于列出所有産品,而後者則打開單個頁面。

flask_app / static / css / main.css

body {
  padding-top: 50px;
}
.top-pad {
  padding: 40px 15px;
  text-align: center;
}
           

該檔案包含一些自定義CSS,我添加了這些自定義CSS可使模闆更清晰易讀。 現在讓我們看一下模闆。

flask_app / templates / base.html

<!DOCTYPE html>
<html >
  <head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Jinja2 Tutorial - Tutsplus</title>
    <link href="{{ url_for('static', filename='css/bootstrap.min.css') }}" target="_blank" rel="external nofollow"  rel="stylesheet">
    <link href="{{ url_for('static', filename='css/main.css') }}" target="_blank" rel="external nofollow"  rel="stylesheet">
  </head>
  <body>
    <div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
      <div class="container">
        <div class="navbar-header">
          <a class="navbar-brand" href="{{ url_for('home')}}" target="_blank" rel="external nofollow" >Tutsplus - Jinja2 Tutorial</a>
        </div>
      </div>
    </div>
    <div class="container">
      {% block container %}{% endblock %}
    </div>
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
    <script src="{{ url_for('static', filename='js/bootstrap.min.js') }}"></script>
  </body>
</html>
           

請注意使用

url_for()

為靜态檔案和其他連結建立URL。 這是Flask提供的非常友善的工具。 在文檔中閱讀有關此内容的更多資訊。 這裡要注意的另一個重要點是

{% block container %}{% endblock %}

的用法,這是Jinja2的非常關鍵的組成部分,緻力于使模闆子產品化和可繼承。 接下來的幾個檔案将使這一點更加清晰。

flask_app / templates / home.html

{% extends 'base.html' %}

{% block container %}
  <div class="top-pad">
    {% for id, product in products.iteritems() %}
      <div class="well">
        <h2>
          <a href="{{ url_for('product', key=id) }}" target="_blank" rel="external nofollow" >{{product['name'] }}</a>
          <small>$ {{ product['price'] }}</small>
        </h2>
      </div>
    {% endfor %}
  </div>
{% endblock %}
           

了解此模闆如何擴充

base.html

并提供

{% block container %}

{% for %}

行為就像普通的for循環一樣,在我們用來建立産品清單的任何語言中。

flask_app / templates / product.html

{% extends 'home.html' %}

{% block container %}
  <div class="top-pad">
    <h1>{{ product['name'] }}
      <small>{{ product['category'] }}</small>
    </h1>
    <h3>$ {{ product['price'] }}</h3>
  </div>
{% endblock %}
           

上面的模闆實作了單個産品頁面。

現在,通過執行以下指令運作該應用程式。

flask --app=my_app run
           

正在運作的應用看起來像下面的螢幕截圖所示。 隻需在浏覽器中打開http://127.0.0.1:5000/home 。

在Flask中使用Jinja2進行模闆制作:基礎知識

單擊任何産品以檢視單個産品頁面。

在Flask中使用Jinja2進行模闆制作:基礎知識

結論

在本教程中,我們已經看到了如何使用Jinja2在基于Flask的應用程式中布局模闆結構。 我們還看到了如何使用塊來利用模闆中的繼承。

在本系列的下一部分中,我們将看到如何編寫自定義過濾器,自定義上下文處理器和宏。

翻譯自: https://code.tutsplus.com/tutorials/templating-with-jinja2-in-flask-essentials--cms-25571