flask:flask模板——使用Jinja2

dangfulin發表於2020-10-07

一,模板引擎

flask使用Jinja2引擎來渲染模板。

1,什麼是模板

簡單來說,在web應用開發中,後端主要負責業務邏輯,完成請求與相應的邏輯處理及資料讀寫,前端主要負責表現邏輯,完成應用介面表現與互動邏輯。為了實現前後端的解耦,分離前後端邏輯,就可以將表現邏輯分離出來交友模板通過模板引擎渲染來實現。

這樣看來,其實模板就是包含靜態與動態內容的網頁內容。

2,什麼是Jinja2

Jinja是一種現代的、對設計人員友好的Python模板語言。它具有快速、廣泛使用和安全的特性,並且具有可選的沙箱模板執行環境。

3,什麼是模板渲染?

所謂渲染,其實就是向網頁中載入靜態內容及動態內容值的過程。

4,怎樣使用模板

下面是一個最簡單的例子:
1,建立flask專案
這裡以建立flask專案:Hello,Flask!為例。
2,在專案中的templates檔案中建立.html檔案
應用結構及.html內容如下:
在這裡插入圖片描述

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Index</title>
</head>     
<body>
    <h1>Hello World!</h1>
</body>
</html>

3,編寫路由及試圖處理函式
app.py內容如下:

from flask import Flask
from flask import render_template


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


if __name__ == '__main__':
    app.run()
  • 使用render_template()渲染模板

4,執行專案
在這裡插入圖片描述
在這裡插入圖片描述

二,向模板傳參

當然,動態模板才是最常見的,即多是情況下我們是需要將一些內容傳遞給模板進行渲染使用的。

1,傳遞一個引數

app.py:

@app.route('/')
def hello_world():
    content = "首頁內容"
    return render_template('index.html', content=content)

index.html:

<body>
    <h1>{{ content }}</h1>
</body>
  • 通過 {{ var }} 使用傳來的引數值。

在這裡插入圖片描述

2,傳遞多個引數

app.py:

@app.route('/')
def hello_world():
    title = "首頁"
    content = "首頁內容"
    return render_template('index.html',
                           content=content,
                           title=title)

index.html:

<head>
    <meta charset="UTF-8">
    <title>{{ title }}</title>
</head>
<body>
    <h1>{{ content }}</h1>
</body>

在這裡插入圖片描述

3,傳遞所有引數

上面的方法確實可以向模板傳遞多個引數,但是太麻煩了,flask還有另一種方法。
app.py:

@app.route('/')
def hello_world():
    title = "首頁"
    content = "首頁內容"
    return render_template('index.html', **locals())
  • 使用**locals()將所有引數傳遞給了模板,然後選擇性使用。

效果與2是一樣的,

三,簡單的模板語法

詳細的模板語法請參考Jinja2官方文件,這裡只作簡單介紹。

1,delimiters

在上面的模板中我們看到了一些不同於html原生語法的東西:{{ var }}

{{}}這東西叫分隔符,模板語法中的分隔符有好幾個:

{% ... %}用於宣告,比如在使用for控制語句時

{{ ... }}用於列印到模板輸出的表示式,比如之前傳到到的變數(更準確的叫模板上下文)

{# ... #}用於模板註釋

# ... ##用於行語句,就是對語法的簡化

2,if

語法:

{% if condition %}
	do_something
{% elif condition %}
    do_something
{% else %}
    do_something
{% endif %}```
app.py:
```html
@app.route('/<sex>')
def hello_world(sex):
    title = "首頁"
    content = sex
    return render_template('index.html', **locals())

index.html:

<body>
    {% if content == "男" %}
        <h1></h1>
    {% elif content == "女" %}
        <h1></h1>
    {% else %}
        <h1>性別未知</h1>
    {% endif %}
</body>

在這裡插入圖片描述

3,for

語法:

{% for item in iteratable_object %}
    do_something
{% endfor %}```
app.py:
```html
@app.route('/')
def hello_world():
    title = "首頁"
    content = [
        {'name': '張三', 'age': 10},
        {'name': '李四', 'age': 11},
        {'name': '王五', 'age': 12},
    ]
    return render_template('index.html', **locals())

模板:

<body>
    <h1>人員資訊:</h1>
    {% for info in content %}
        <span>{{ info.name }}  {{ info.age }}</span>
        <br>
    {% endfor %}
</body>

在這裡插入圖片描述

4,filters

變數可以通過過濾器修改。 過濾器由豎線符號 | 與變數分開,並且括號中可以包含可選引數。 可以連結多個過濾器。 一個濾波器的輸出將應用於下一個。

flask提供了許多內建過濾器

模板:

<body>
    <h1>人員資訊:</h1>
    {%for info in content|sort(attribute="age")|sort(reverse=true,attribute="name")%}
        <span>{{ info.name }}  {{ info.age }}</span>
        <br>
    {% endfor %}
</body>

在這裡插入圖片描述
過濾器本質就是一個處理函式,能自定義過濾器:

  1. 定義處理函式
  2. 使用
  3. 在模板中使用

自定義過濾器如下:
app.py:

@app.route('/')
def hello_world():
    title = "首頁"
    content = [
        {'name': '張三', 'age': 10},
        {'name': '李四', 'age': 11},
        {'name': '王五', 'age': 12},
    ]
    return render_template('index.html', **locals())


def do_add_age_number(age_number):
    age = age_number + 3
    return age


app.add_template_filter(do_add_age_number, 'add_age_number')

模板:

<body>
    <h1>人員資訊:</h1>
    {%for info in content %}
        <span>{{ info.name }} : {{ info.age | add_age_number }}</span>
        <br>
    {% endfor %}
</body>

在這裡插入圖片描述

5,Macro

巨集可與常規程式語言中的功能媲美。 它們有助於將常用的慣用語放入可重複使用的功能中,從而使一個巨集可以被多個模板使用。

1,宣告與呼叫
模板:

<body>
    <h1>人員資訊:</h1>
    {% macro input(name, value='', type='text', size=20, placeholder="在這裡輸入內容") -%}
        <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" placeholder="{{ placeholder }}">
    {% endmacro %}

    <div class="info">
        <p>使用者:{{ input('username') }}</p>
        <p>密碼:{{ input('password', type='password') }}</p>
        <p>登入:{{ input(type='submit',   value="登入") }}</p>
    </div>
</body>

在這裡插入圖片描述
2,規範化使用巨集
就像C語言中的標頭檔案概念一樣,我們最好將巨集統一放置:
在這裡插入圖片描述
使用時再匯入:

    {% import "macros/login_form.html" as login_form %}
    <div class="info">
        <p>使用者:{{ login_form.input('username') }}</p>
        <p>密碼:{{ login_form.input('password', type='password') }}</p>
        <p>登入:{{ login_form.input(type='submit',   value="登入") }}</p>
    </div>

3,include
include可以將一個模板匯入到指定模板中。
在這裡插入圖片描述
在這裡插入圖片描述

6,set與with

set與with都能在模板中設定變數,前者為全作用域,後者為本標籤作用域,這與DTL是一樣的。

<body>
    {% include "included.html" %}
    {% set massage="人員資訊修改:" %}
    <h1>{{ massage }}</h1>
    {% import "macros/login_form.html" as login_form %}
    {% with warning="注意保管系統管理員密保卡內容!" %}
    <div class="info">
        <p>使用者:{{ login_form.input('username') }}</p>
        <p>密碼:{{ login_form.input('password', type='password') }}</p>
        <p>登入:{{ login_form.input(type='submit',   value="登入") }}</p>
    </div>
    <div class="warning">
        <span>{{ warning }}</span>
    </div>
    {% endwith %}
</body>

在這裡插入圖片描述

四,在模板中載入靜態檔案

css與JavaScript的引入,使得網頁具有更豐富的內容與互動方式,它們將讓使用者獲得更好的使用體驗。

除了直接在模板檔案中使用<script>標籤包含靜態內容,更推薦的方法是將它們統一放入static檔案中。專案結構如下:
在這裡插入圖片描述

模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
{#    <script src="{{ url_for('static', filename='js/jquery-3.3.1/jquery-3.3.1.js') }}"></script>#}

<script type="text/javascript" src="static/js/jquery-3.3.1/jquery-3.3.1.js"></script>
<link rel="stylesheet" href="{{ url_for('static',filename='css/car.css') }}">
</head>
<body>
{#測試jquery是否載入#}
<script>
    if(jQuery) {
        alert('jQuery已載入!');
    }
    else {
        alert('jQuery未載入!');
    }
</script>
<div class="img">
<img src="{{ url_for('static', filename='images/car.jpg') }}"></img>
</div>
</body>
</html>

五,模板繼承

前面講的include能將一個模板嵌入到另一個模板,模板繼承允許一個模板繼承另一個模板並進行一些修改。

父模板中新增{% block partname %}{% endblock %}就允許子模板對這塊內容進行修改。

子模板使用{% extends %}繼承父模板,並在{% block partname %}{% endblock %}中新增自己的內容。

專案結構如下:
在這裡插入圖片描述
父模板base.html:

<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
</head>
<body>
{% block body %}
    這是父模板中的內容
{% endblock %}
</body>
</html>

子模板index.html:

{% extends "base.html" %}

{% block title %}網站首頁{% endblock %}

{% block body %}
    {{ super() }}
    <h4>這是子模板的內容!</h4>
{% endblock %}
  • 使用{{ super() }}保留父模板內容

在這裡插入圖片描述

相關文章