Python模板引擎Jinja2(一)

前言

來啦老鐵!

筆者近期在工作中遇到將測試數(shù)據(jù)可視化的需求杈湾,且在Python語言背景下,當時借用的是團隊既有經(jīng)驗,即:

  • 模板引擎技術(shù)

而模板引擎使用:Jinja2

看過筆者的Spring Boot全家桶系列文章的同學一定不會陌生析恢,我們曾在文章Spring Boot視圖技術(shù)中,一起學習了java體系下的視圖技術(shù)(模板引擎技術(shù))秧饮,咱們今天也來學習學習Python體系下的模板引擎技術(shù)吧映挂!

學習路徑

  1. 常見的Python模板引擎有哪些?
  2. Jinja2簡介盗尸;
  3. Jinja2入門使用柑船;
  4. Jinja2的基礎(chǔ)知識點;

1. 常見的Python模板引擎有哪些泼各?

首先我們來看看網(wǎng)上的大佬們都玩過哪些Python的模板引擎吧:

  • pyTemplate
  • pyTenjin
  • Tornado.template
  • PyJade
  • Genshi
  • Django
  • Smarty
  • Mako
  • Jinja2
  • 等鞍时。

這么多?筆者只聽過Django和Jinja2,孤陋寡聞了逆巍,有興趣的朋友請移步百度~

2. Jinja2簡介及塘;

來源:https://www.cnblogs.com/yanjiayi098-001/p/11701150.html

1). Jinja2介紹:

jinja2是Flask作者開發(fā)的一個模板系統(tǒng),起初是仿django模板的一個模板引擎蒸苇,為Flask提供模板支持磷蛹,由于其靈活,快速和安全等優(yōu)點被廣泛使用溪烤。

2). Jinja2的優(yōu)點:
  • 相對于Template味咳,jinja2更加靈活,它提供了控制結(jié)構(gòu)檬嘀,表達式和繼承等槽驶;
  • 相對于Mako,jinja2僅有控制結(jié)構(gòu)鸳兽,不允許在模板中編寫太多的業(yè)務(wù)邏輯掂铐;
  • 相對于Django模板,jinja2性能更好揍异;
  • Jinja2模板的可讀性很棒全陨。

3. Jinja2入門使用;

話不多說衷掷,咱直接開整辱姨,代碼倉庫:

我們直接開始擼一個簡單的渲染例子,當然戚嗅,在使用Jinja2前雨涛,需要安裝Jinja2喲:

pip3 install jinja2
1). 創(chuàng)建模板文件;

模板文件即html文件懦胞,我們在項目內(nèi)創(chuàng)建一個python包替久,如resources包,在resources包內(nèi)創(chuàng)建一個模板文件夾templates躏尉,用于存放Jinja模板蚯根,最后在templates文件夾下創(chuàng)建一模板文件如:jinja2_demo_1.html;

2). 編寫模板文件胀糜;

在jinja2_demo_1.html文件中稼锅,編寫簡單的Jinja模板,代碼如下:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Jinja2-demo-1</title>
</head>
<body>
<table border="1">
    <thead>
    <tr>
        <th>INDEX</th>
        <th>STATUS</th>
        <th>MESSAGE</th>
        <th>CREATED_WHEN</th>
    </tr>
    </thead>

    <tbody>
    <tr>
        <td>{{index}}</td>
        <td>{{status}}</td>
        <td>{{message}}</td>
        <td>{{created_when}}</td>
    </tr>
    </tbody>
</table>
</body>
</html>

我們會發(fā)現(xiàn)僚纷,模板中沒有寫死的數(shù)據(jù)矩距,而是以{{}}符號包裹變量,如果這時候直接瀏覽器打開resources/templates/jinja2_demo_1.html文件怖竭,效果為:

瀏覽器打開模板文件

沒錯锥债,就是個模板而已,沒有真實值。接下來我們就來將{{}}符號包裹變量變成我們想展示的值吧哮肚!

3). 創(chuàng)建模板渲染邏輯處理類登夫;

在項目根目錄下創(chuàng)建一個python包,如utils包允趟,在包內(nèi)創(chuàng)建一個python類恼策,如reportUtil.py,類中編寫一簡單的模板渲染邏輯潮剪,如下:

#!/usr/local/bin/python3
# -*- coding:utf-8 -*-

__author__ = "diren"
__date__ = "2021-01-03 15:50"

import os
import time

from jinja2 import Environment, PackageLoader


class ReportUtil:
    def __init__(self):
        pass

    def create_jinja2_demo_1_html(self):
        index = 1
        status = "成功"
        message = "這是一個測試文本"
        created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        env = Environment(loader=PackageLoader('resources', 'templates'))
        template_name = "jinja2_demo_1.html"
        template = env.get_template(template_name)
        html = template.render(index=index, message=message, created_when=created_when, status=status)

        current_dir = os.getcwd()
        output_dir = os.path.join(current_dir, "../resources/output/")
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)
        os.chdir(output_dir)

        fo = open(template_name, "w")
        fo.writelines(html)
        fo.close()
        os.chdir(current_dir)
        print(f"create {template_name}:", "完成")


if __name__ == "__main__":
    ReportUtil().create_jinja2_demo_1_html()

這里稍微講解一下我們的目的:

  • 我們希望通過reportUtil.py涣楷,將一組數(shù)據(jù)渲染進resources/templates/jinja2_demo_1.html文件中表格的第一行;
  • 渲染的數(shù)據(jù)為:
index = 1
status = "成功"
message = "這是一個測試文本"
created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
  • 渲染后的文件存儲于resources/output/jinja2_demo_1.html中,

渲染預期為一個簡單表格抗碰;

4). 項目整體結(jié)構(gòu)狮斗;
項目整體結(jié)構(gòu)
5). 演示;

運行reportUtil.py弧蝇,我們能看到resources包下生成了一個output文件夾碳褒,output文件夾下有一個html文件:jinja2_demo_1.html,該文件就是我們在reportUtil.py渲染出來的靜態(tài)html文件:

渲染html

瀏覽器打開resources/output/jinja2_demo_1.html文件:

瀏覽器訪問html

嗯两芳,沒錯,原來{{}}符號包裹的變量翼闹,均變成我們reportUtil.py代碼中想渲染的真實值了荒叶,渲染演示成功蚕钦!是不是很簡單呀!

上述泞当,演示了一個非常簡單的Jinja2使用方法询兴,接下來我們一起來邊學習Jinja2的常用功能暴匠,邊碼代碼、邊演示瀑志、邊學習吧!

4. Jinja2的基礎(chǔ)知識點湖饱;

這里羅列一下基礎(chǔ)知識點:

  • 基本語法;
  • 運算符仅仆;
  • 轉(zhuǎn)義方法墓拜;
  • 測試器;
  • 如何在模版頁面中引入靜態(tài)文件肠槽?
  • 過濾器;
  • 宏;
  • 模板繼承寂纪;

1). 基本語法孝冒;

  • 注釋 {#...#}
    例如:{#這是一個注釋#}柬姚,這一行代碼是不會被渲染、處理的庄涡,起注釋作用量承;

  • 變量取值 {{...}}

如上面的例子, {{}}是占位符穴店,Jinja2渲染時會將這些占位符替換成真實值撕捍。它支持python中的所有數(shù)據(jù)類型,如字符串泣洞、字典忧风、列表等。

  • 控制結(jié)構(gòu) {% ... %}

該符號包裹的內(nèi)容表示控制結(jié)構(gòu)球凰,如分支狮腿、循環(huán),我們來演示一下:

(1). if語句:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Jinja2-demo-1</title>
</head>
<body>
<table border="1">
    <thead>
    <tr>
        <th>INDEX</th>
        <th>STATUS</th>
        <th>MESSAGE</th>
        <th>CREATED_WHEN</th>
    </tr>
    </thead>

    {#這是一個注釋#}
    <tbody>
    {% if index==1 %}
    <tr>
        <td>{{index}}</td>
        <td>{{status}}</td>
        <td>{{message}}</td>
        <td>{{created_when}}</td>
    </tr>
    {% elif index==2 %}
    <tr>
        <td>{{index}}</td>
        <td>{{status}}</td>
    </tr>
    {% else %}
    <tr>
        <td>{{index}}</td>
        <td>{{status}}</td>
        <td>{{message}}</td>
    </tr>
    {% endif %}
    </tbody>
</table>
</body>
</html>

很簡單弟蚀,當index為1蚤霞,2,其他值時义钉,表格顯示的內(nèi)容略有差異:

index為1時
index為2時
index為其他值時
(2). for語句:

我們使用for語句昧绣,演示渲染一個含有多條數(shù)據(jù)的表格,并且為了演示效果捶闸,我順便從網(wǎng)上找了個樣式夜畴,稍作調(diào)整,創(chuàng)建新的模板文件jinja2_demo_2.html:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Jinja2-demo-2</title>
</head>
<body>
<title>{{title}}</title>
<div class="card">
    <div class="card-title">
        <span style="color: #ffffff; font-size: 28px; font-weight: 700">{{title}}</span>
    </div>
    <div class="card-content">
        <div>最終結(jié)果:{{ status }}</div>
        <div>發(fā)布日期:{{ created_when }}</div>
    </div>
</div>
<br>

<table class="pure-table pure-table-bordered">
    <thead>
    <tr>
        <th>INDEX</th>
        <th>STATUS</th>
        <th>MESSAGE</th>
        <th>CREATED_WHEN</th>
    </tr>
    </thead>

    <tbody>
    {% for item in details %}
    <tr class="{{ loop.cycle('odd', 'even') }}">
       <td>{{item.index}}</td>
        <td>{{item.status}}</td>
        <td>{{item.message}}</td>
        <td>{{item.created_when}}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>
</body>
</html>
<style type="text/css">
    .odd {

    }

    .even {
        background-color: #F5F5F5;
    }

    .card-title {
        -moz-border-bottom-colors: none;
        -moz-border-left-colors: none;
        -moz-border-right-colors: none;
        -moz-border-top-colors: none;
        background-color: #B0C4DE;
        border-color: #e7eaec;
        -webkit-border-image: none;
        -o-border-image: none;
        border-image: none;
        border-style: solid solid none;
        border-width: 4px 0 0;
        color: inherit;
        margin-bottom: 0;
        padding: 14px 15px 7px;
        min-height: 48px;
    }

    .card-content {
        background-color: #fff;
        color: inherit;
        padding: 15px 20px 20px;
        border-color: #e7eaec;
        -webkit-border-image: none;
        -o-border-image: none;
        border-image: none;
        border-style: solid solid none;
        border-width: 1px 0
    }

    .card-content div {
        padding: 6px;
    }

    .card {
        box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
        text-align: left;
    }

    html {
        font-family: sans-serif;
        -ms-text-size-adjust: 100%;
        -webkit-text-size-adjust: 100%;
    }

    body {
        margin: 10px;
    }

    table {
        border-collapse: collapse;
        border-spacing: 0;
        width: 100%;
        max-width: 100%;
        margin-bottom: 20px;
    }

    td,th {
        padding: 0;
    }

    .pure-table {
        border-collapse: collapse;
        border-spacing: 0;
        empty-cells: show;
        border: 1px solid #cbcbcb;
    }

    .pure-table caption {
        color: #000;
        font: italic 85%/1 arial,sans-serif;
        padding: 1em 0;
        text-align: center;
    }

    .pure-table td,.pure-table th {
        border-left: 1px solid #cbcbcb;
        border-width: 0 0 0 1px;
        font-size: inherit;
        margin: 0;
        overflow: visible;
        padding: .5em 1em;
    }

    .pure-table thead {
        background-color: #00BFFF;
        color: #000;
        text-align: left;
        vertical-align: bottom;
    }

    .pure-table td {
        background-color: transparent;
    }

    .pure-table-bordered td {
        border-bottom: 1px solid #cbcbcb;
    }

    .pure-table-bordered tbody>tr:last-child>td {
        border-bottom-width: 0;
    }
</style>

reportUtil.py中也新增一渲染方法create_jinja2_demo_2_report删壮,代碼如下:

#!/usr/local/bin/python3
# -*- coding:utf-8 -*-

__author__ = "diren"
__date__ = "2021-01-03 15:50"

import os
import time

from jinja2 import Environment, PackageLoader


class ReportUtil:
    def __init__(self):
        pass

    def create_jinja2_demo_1_html(self):
        index = 1
        status = "成功"
        message = "這是一個測試文本"
        created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        env = Environment(loader=PackageLoader('resources', 'templates'))
        template_name = "jinja2_demo_1.html"
        template = env.get_template(template_name)
        html = template.render(index=index, message=message, created_when=created_when, status=status)

        current_dir = os.getcwd()
        output_dir = os.path.join(current_dir, "../resources/output/")
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)
        os.chdir(output_dir)

        fo = open(template_name, "w")
        fo.writelines(html)
        fo.close()
        os.chdir(current_dir)
        print(f"create {template_name}:", "完成")

    def create_jinja2_demo_2_html(self):
        title = "測試報告"
        status = "失敗"
        created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

        details = [{
            "status": "成功",
            "message": "測試文本1",
            "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        }, {
            "index": 2,
            "status": "失敗",
            "message": "測試文本2",
            "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        }, {
            "index": 3,
            "status": "成功",
            "message": "測試文本2",
            "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        }]

        env = Environment(loader=PackageLoader('resources', 'templates'))
        template_name = 'jinja2_demo_2.html'
        template = env.get_template(template_name)
        html = template.render(title=title, status=status, created_when=created_when, details=details)

        current_dir = os.getcwd()
        output_dir = os.path.join(current_dir, "../resources/output/")
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)
        os.chdir(output_dir)

        fo = open(template_name, "w")
        fo.writelines(html)
        fo.close()
        os.chdir(current_dir)
        print(f"create {template_name}:", "完成")


if __name__ == "__main__":
    ReportUtil().create_jinja2_demo_1_html()
    ReportUtil().create_jinja2_demo_2_html()

運行reportUtil.py后:
渲染新html
for語句渲染效果

這樣贪绘,我們順利將多條數(shù)據(jù)渲染進模板進行展示,數(shù)據(jù)為:

        title = "測試報告"
        status = "失敗"
        created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

        details = [{
            "index": 1,
            "status": "成功",
            "message": "測試文本1",
            "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        }, {
            "index": 2,
            "status": "失敗",
            "message": "測試文本2",
            "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        }, {
            "index": 3,
            "status": "成功",
            "message": "測試文本2",
            "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        }]

其中表格主題數(shù)據(jù)為:details央碟;

我們還可以在循環(huán)中加入條件語句税灌,如:
    <tbody>
    {% for item in details %}
    <tr class="{{ loop.cycle('odd', 'even') }}">
        <td>{{item.index}}</td>
        <td>{{item.status}}</td>
        <td>{{item.message}}</td>
        <td>{{item.created_when}}</td>
    </tr>
    {% else %}
    <tr>
        <td>no data found</td>
        <td>no data found</td>
        <td>no data found</td>
        <td>no data found</td>
    </tr>
    {% endfor %}
    </tbody>

則當details為空時,表格會展示一行no data found的數(shù)據(jù)亿虽;

details為空時
我們也可以遍歷python字典進行展示菱涤,如:

模板:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Jinja2-demo-3</title>
</head>
<body>
<title>{{title}}</title>
<div class="card">
    <div class="card-title">
        <span style="color: #ffffff; font-size: 28px; font-weight: 700">{{title}}</span>
    </div>
    <div class="card-content">
        <div>最終結(jié)果:{{ status }}</div>
        <div>發(fā)布日期:{{ created_when }}</div>
    </div>
</div>
<br>

<table class="pure-table pure-table-bordered">
    <thead>
    <tr>
        <th>KEY</th>
        <th>VALUE</th>
    </tr>
    </thead>

    <tbody>
    {% for key,value in test_dict.items() %}
    <tr class="{{ loop.cycle('odd', 'even') }}">
        <td>{{key}}</td>
        <td>{{value}}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>
</body>
</html>
<style type="text/css">
    .odd {

    }

    .even {
        background-color: #F5F5F5;
    }

    .card-title {
        -moz-border-bottom-colors: none;
        -moz-border-left-colors: none;
        -moz-border-right-colors: none;
        -moz-border-top-colors: none;
        background-color: #B0C4DE;
        border-color: #e7eaec;
        -webkit-border-image: none;
        -o-border-image: none;
        border-image: none;
        border-style: solid solid none;
        border-width: 4px 0 0;
        color: inherit;
        margin-bottom: 0;
        padding: 14px 15px 7px;
        min-height: 48px;
    }

    .card-content {
        background-color: #fff;
        color: inherit;
        padding: 15px 20px 20px;
        border-color: #e7eaec;
        -webkit-border-image: none;
        -o-border-image: none;
        border-image: none;
        border-style: solid solid none;
        border-width: 1px 0
    }

    .card-content div {
        padding: 6px;
    }

    .card {
        box-shadow: 0 4px 8px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19);
        text-align: left;
    }

    html {
        font-family: sans-serif;
        -ms-text-size-adjust: 100%;
        -webkit-text-size-adjust: 100%;
    }

    body {
        margin: 10px;
    }

    table {
        border-collapse: collapse;
        border-spacing: 0;
        width: 100%;
        max-width: 100%;
        margin-bottom: 20px;
    }

    td,th {
        padding: 0;
    }

    .pure-table {
        border-collapse: collapse;
        border-spacing: 0;
        empty-cells: show;
        border: 1px solid #cbcbcb;
    }

    .pure-table caption {
        color: #000;
        font: italic 85%/1 arial,sans-serif;
        padding: 1em 0;
        text-align: center;
    }

    .pure-table td,.pure-table th {
        border-left: 1px solid #cbcbcb;
        border-width: 0 0 0 1px;
        font-size: inherit;
        margin: 0;
        overflow: visible;
        padding: .5em 1em;
    }

    .pure-table thead {
        background-color: #00BFFF;
        color: #000;
        text-align: left;
        vertical-align: bottom;
    }

    .pure-table td {
        background-color: transparent;
    }

    .pure-table-bordered td {
        border-bottom: 1px solid #cbcbcb;
    }

    .pure-table-bordered tbody>tr:last-child>td {
        border-bottom-width: 0;
    }
</style>

其中,關(guān)鍵代碼:{% for key,value in test_dict.items() %}...{% endfor %}

reportUtil.py中新增create_jinja2_demo_3_html方法:

#!/usr/local/bin/python3
# -*- coding:utf-8 -*-

__author__ = "diren"
__date__ = "2021-01-03 15:50"

import os
import time

from jinja2 import Environment, PackageLoader


class ReportUtil:
    def __init__(self):
        pass

    def create_jinja2_demo_1_html(self):
        index = 1
        status = "成功"
        message = "這是一個測試文本"
        created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        env = Environment(loader=PackageLoader('resources', 'templates'))
        template_name = "jinja2_demo_1.html"
        template = env.get_template(template_name)
        html = template.render(index=index, message=message, created_when=created_when, status=status)

        current_dir = os.getcwd()
        output_dir = os.path.join(current_dir, "../resources/output/")
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)
        os.chdir(output_dir)

        fo = open(template_name, "w")
        fo.writelines(html)
        fo.close()
        os.chdir(current_dir)
        print(f"create {template_name}:", "完成")

    def create_jinja2_demo_2_html(self):
        title = "測試報告"
        status = "失敗"
        created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

        details = [{
            "status": "成功",
            "message": "測試文本1",
            "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        }, {
            "index": 2,
            "status": "失敗",
            "message": "測試文本2",
            "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        }, {
            "index": 3,
            "status": "成功",
            "message": "測試文本2",
            "created_when": time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
        }]

        env = Environment(loader=PackageLoader('resources', 'templates'))
        template_name = 'jinja2_demo_2.html'
        template = env.get_template(template_name)
        html = template.render(title=title, status=status, created_when=created_when, details=details)

        current_dir = os.getcwd()
        output_dir = os.path.join(current_dir, "../resources/output/")
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)
        os.chdir(output_dir)

        fo = open(template_name, "w")
        fo.writelines(html)
        fo.close()
        os.chdir(current_dir)
        print(f"create {template_name}:", "完成")

    def create_jinja2_demo_3_html(self):
        title = "人員信息"
        status = "采集成功"
        created_when = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

        test_dict = {
            "name": "dylanz",
            "gender": "male",
            "age": 18,
            "professional": "TA"
        }

        env = Environment(loader=PackageLoader('resources', 'templates'))
        template_name = 'jinja2_demo_3.html'
        template = env.get_template(template_name)
        html = template.render(title=title, status=status, created_when=created_when, test_dict=test_dict)

        current_dir = os.getcwd()
        output_dir = os.path.join(current_dir, "../resources/output/")
        if not os.path.exists(output_dir):
            os.mkdir(output_dir)
        os.chdir(output_dir)

        fo = open(template_name, "w")
        fo.writelines(html)
        fo.close()
        os.chdir(current_dir)
        print(f"create {template_name}:", "完成")


if __name__ == "__main__":
    ReportUtil().create_jinja2_demo_1_html()
    ReportUtil().create_jinja2_demo_2_html()
    ReportUtil().create_jinja2_demo_3_html()

效果:

遍歷字典效果

Jinja2中for循環(huán)內(nèi)置常量

細心的同學會發(fā)現(xiàn)洛勉,在for循環(huán)中粘秆,我們使用loop.cycle來交替使用單元格樣式'odd', 'even',loop.cycle為Jinja2中循環(huán)計數(shù)內(nèi)置變量收毫,而Jinja2還擁有其他循環(huán)內(nèi)置常量攻走,有:

Jinja2中for循環(huán)內(nèi)置常量-來自網(wǎng)絡(luò)

篇幅有限殷勘,請讀者自行了解、嘗試哈昔搂!

2). 運算符玲销;

+號運算符:可以完成數(shù)字相加,字符串相加摘符,列表相加痒玩。但是并不推薦使用+運算符來操作字符串,字符串相加應該使用~運算符议慰。
-號運算符:只能針對兩個數(shù)字相減蠢古。
/號運算符:對兩個數(shù)進行相除。
%號運算符:取余運算别凹。
*號運算符:乘號運算符草讶,并且可以對字符進行相乘。
**號運算符:次冪運算符炉菲,比如2**3=8堕战。
in操作符:跟python中的in一樣使用,比如{{1 in [1,2,3]}}返回true拍霜。
~號運算符:拼接多個字符串嘱丢,比如{{"Hello" ~ "World"}}將返回HelloWorld。

3). 轉(zhuǎn)義方法;

開啟轉(zhuǎn)義:
在模板渲染字符串的時候祠饺,字符串有可能包括一些非常危險的字符比如<越驻、>等,這些字符會破壞掉原來HTML標簽的結(jié)構(gòu)道偷,更嚴重的可能會發(fā)生XSS跨域腳本攻擊缀旁,因此如果碰到<、>這些字符的時候勺鸦,應該轉(zhuǎn)義成HTML能正確表示這些字符的寫法并巍。

  • 對引用的變量值進行轉(zhuǎn)義:{{ 變量名|e }}或{{ 變量名|escape }}
  • 將代碼段進行自動轉(zhuǎn)義:{%autoescape true%}...{%endautoescape%},如:
{% autoescape true %}
<p>自動轉(zhuǎn)義已開啟</p>
<p>{{ 變量引用值會被自動轉(zhuǎn)義 }}</p>
{% endautoescape %}

關(guān)閉轉(zhuǎn)義:

  • 對引用的變量值關(guān)閉轉(zhuǎn)義:{{變量名|safe }}
  • 將代碼段關(guān)閉自動轉(zhuǎn)義:{%autoescape false%}...{%endautoescape%}换途,如:
{% autoescape false %}
<p>自動轉(zhuǎn)義已關(guān)閉</p>
<p>{{ 變量引用值不會被自動轉(zhuǎn)義 }}</p>
{% endautoescape %}
4). 測試器;

測試器主要用來判斷一個值是否滿足某種類型懊渡,語法是:if...is...,例如:

{% if 變量名 is string%}
字符串變量的值為: {{ 變量名 }}
{% else %}
不是字符串變量
{% endif %}

其中string就是測試器军拟。

Jinja2中測試器有:

  • callable:是否可調(diào)用剃执;
  • defined:是否已經(jīng)被定義了;
  • escaped:是否已經(jīng)被轉(zhuǎn)義了吻谋;
  • upper:是否全是大寫忠蝗;
  • lower:是否全是小寫现横;
  • string:是否是一個字符串漓拾;
  • sequence:是否是一個序列阁最;
  • number:是否是一個數(shù)字;
  • odd:是否是奇數(shù)骇两;
  • even:是否是偶數(shù)速种;
5). 如何在模版頁面中引入靜態(tài)文件?

在Jinja中加載靜態(tài)文件只需要通過url_for全局函數(shù)就可以實現(xiàn)低千,例如引入static目錄下的style.css文件:

<style type="text/css" href="{{ url_for('static',filename='style.css') }}"/>

該用法需要在Flask框架下配阵,指定靜態(tài)文件路徑方可,此處開卷有益~

6). 過濾器;

前面提到的幾個用法:{{ 變量名|e }}或{{ 變量名|escape }}示血、{{變量名|safe }}棋傍,這些其實是利用了Jinja2中的過濾器功能,過濾器是通過“|”符號進行使用的难审,符號前為過濾器輸入瘫拣,符號后為過濾器函數(shù)、方法告喊、規(guī)則麸拄,意思是變量值不直接進行渲染,而是根據(jù)過濾器函數(shù)的規(guī)則進行轉(zhuǎn)換后黔姜,再進行渲染拢切。

過濾器函數(shù)可將變量值轉(zhuǎn)成絕對值、大小寫秆吵、轉(zhuǎn)義等再進行渲染淮椰,Jinja2擁有許多過濾器規(guī)則,我們一起來學習一下吧:
來源:https://www.cnblogs.com/songyifan427/p/10144506.html

  • abs(value):返回一個數(shù)值的絕對值纳寂,示例:-1|abs实苞;
  • default(value,default_value,boolean=false):如果當前變量沒有值,則會使用參數(shù)中的值來代替烈疚。示例:name|default('xiaotuo')——如果name不存在黔牵,則會使用xiaotuo來替代;boolean=False默認是在只有這個變量為undefined的時候才會使用default中的值爷肝,如果想使用python的形式判斷是否為false猾浦,則可以傳遞boolean=true。也可以使用or來替換灯抛;
  • escape(value)或e:轉(zhuǎn)義字符金赦,會將<、>等符號轉(zhuǎn)義成HTML中的符號对嚼。示例:content|escape或content|e夹抗;
  • first(value):返回一個序列的第一個元素。示例:names|first纵竖;
  • format(value,*arags,**kwargs):格式化字符串漠烧。比如:
{{ "%s" - "%s"|format('Hello?',"Foo!") }}
將輸出:Helloo? - Foo!
  • last(value):返回一個序列的最后一個元素杏愤。示例:names|last;

  • length(value):返回一個序列或者字典的長度已脓。示例:names|length珊楼;

  • join(value,d=u''):將一個序列用d這個參數(shù)的值拼接成字符串;

  • safe(value):如果開啟了全局轉(zhuǎn)義度液,那么safe過濾器會將變量關(guān)掉轉(zhuǎn)義厕宗。示例:content_html|safe;

  • int(value):將值轉(zhuǎn)換為int類型堕担;

  • float(value):將值轉(zhuǎn)換為float類型已慢;

  • lower(value):將字符串轉(zhuǎn)換為小寫;

  • upper(value):將字符串轉(zhuǎn)換為小寫霹购;

  • replace(value,old,new): 替換將old替換為new的字符串蛇受;

  • truncate(value,length=255,killwords=False):截取length長度的字符串;

  • striptags(value):刪除字符串中所有的HTML標簽厕鹃,如果出現(xiàn)多個空格兢仰,將替換成一個空格;

  • trim:截取字符串前面和后面的空白字符剂碴;

  • string(value):將變量轉(zhuǎn)換成字符串把将;

  • wordcount(s):計算一個長字符串中單詞的個數(shù);

我們可以將過濾器理解為高級版的運算符忆矛!

知識點有點多察蹲,再學下去是不是要吐了?
那我們今天就到此為止吧催训,下一篇洽议,我們再繼續(xù)學習Jinja2的另外2個重要概念:

  • 模板繼承

看著就很有食欲啊,敬請期待漫拭!

如果本文對您有幫助亚兄,麻煩動動手指點點贊?

謝謝采驻!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末审胚,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子礼旅,更是在濱河造成了極大的恐慌膳叨,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,252評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痘系,死亡現(xiàn)場離奇詭異菲嘴,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,886評論 3 399
  • 文/潘曉璐 我一進店門龄坪,熙熙樓的掌柜王于貴愁眉苦臉地迎上來昭雌,“玉大人,你說我怎么就攤上這事悉默。” “怎么了苟穆?”我有些...
    開封第一講書人閱讀 168,814評論 0 361
  • 文/不壞的土叔 我叫張陵抄课,是天一觀的道長。 經(jīng)常有香客問我雳旅,道長跟磨,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,869評論 1 299
  • 正文 為了忘掉前任攒盈,我火速辦了婚禮抵拘,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘型豁。我一直安慰自己僵蛛,他們只是感情好,可當我...
    茶點故事閱讀 68,888評論 6 398
  • 文/花漫 我一把揭開白布迎变。 她就那樣靜靜地躺著充尉,像睡著了一般。 火紅的嫁衣襯著肌膚如雪衣形。 梳的紋絲不亂的頭發(fā)上驼侠,一...
    開封第一講書人閱讀 52,475評論 1 312
  • 那天,我揣著相機與錄音谆吴,去河邊找鬼倒源。 笑死,一個胖子當著我的面吹牛句狼,可吹牛的內(nèi)容都是我干的笋熬。 我是一名探鬼主播,決...
    沈念sama閱讀 41,010評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼腻菇,長吁一口氣:“原來是場噩夢啊……” “哼突诬!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起芜繁,我...
    開封第一講書人閱讀 39,924評論 0 277
  • 序言:老撾萬榮一對情侶失蹤旺隙,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后骏令,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蔬捷,經(jīng)...
    沈念sama閱讀 46,469評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,552評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了周拐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铡俐。...
    茶點故事閱讀 40,680評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖妥粟,靈堂內(nèi)的尸體忽然破棺而出审丘,到底是詐尸還是另有隱情,我是刑警寧澤勾给,帶...
    沈念sama閱讀 36,362評論 5 351
  • 正文 年R本政府宣布滩报,位于F島的核電站,受9級特大地震影響播急,放射性物質(zhì)發(fā)生泄漏脓钾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,037評論 3 335
  • 文/蒙蒙 一桩警、第九天 我趴在偏房一處隱蔽的房頂上張望可训。 院中可真熱鬧,春花似錦捶枢、人聲如沸握截。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,519評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽川蒙。三九已至,卻和暖如春长已,著一層夾襖步出監(jiān)牢的瞬間畜眨,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,621評論 1 274
  • 我被黑心中介騙來泰國打工术瓮, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留康聂,地道東北人。 一個月前我還...
    沈念sama閱讀 49,099評論 3 378
  • 正文 我出身青樓胞四,卻偏偏與公主長得像恬汁,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子辜伟,可洞房花燭夜當晚...
    茶點故事閱讀 45,691評論 2 361

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