<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Flask 和 Django 附帶了強大的 Jinja 模板語言。
對於之前沒有接觸過模板語言的人來說,這類語言基本上就是包含一些變數,當準備渲染呈現 HTML 時,它們會被實際的值替換。
這些變數放在標記或分隔符之前。例如:Jinja 模板使用 {% ... %}
表示迴圈,{{ ... }}
表示一個表示式運算結果返回。
Jinja 模板其實是 html 檔案。一般情況下放在 Flask 工程的
/templates
目錄下
跑下面的各種 demo 之前,確保你已經安裝了 Jinja (pip install jinja2)
>>> from jinja2 import Template >>> t = Template("Hello {{ something }}!") >>> t.render(something="World") u'Hello World!' >>> t = Template("My favorite numbers: {% for n in range(1,10) %}{{n}} " "{% endfor %}") >>> t.render() u'My favorite numbers: 1 2 3 4 5 6 7 8 9 '
這個 demo 展示了模板中的變數(表示式)是如何最終被替換和渲染的。
整個的參考程式碼可以在這裡獲得:HERE
不過博主建議按照下面步驟一步步來:
1)安裝 flask
➜ pip install flask
2)建立工程目錄結構:
➜ mkdir flask_example ➜ cd flask_example ➜ mkdir templates ➜ cd .. ➜ touch run.py ➜ touch requirements.txt
3)編寫 run.py
from flask import Flask, render_template app = Flask(__name__) @app.route("/") def template_test(): return render_template('template.html', my_string="Wheeeee!", my_list=[0,1,2,3,4,5]) if __name__ == '__main__': app.run(debug=True)
這裡,我們建立了一個 /
路由,當我們存取伺服器根路由時,會通過 render_template
將 template.html
渲染,其中 my_string
和 my_list
就是準備傳給模板的實際的值。
4)編寫 template.html 模板
在 templates 目錄下,建立一個 template.html:
<!DOCTYPE html> <html> <head> <title>Flask Template Example</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" media="screen"> <style type="text/css"> .container { max-width: 500px; padding-top: 100px; } </style> </head> <body> <div class="container"> <p>My string: {{my_string}}</p> <p>Value from the list: {{my_list[3]}}</p> <p>Loop through the list:</p> <ul> {% for n in my_list %} <li>{{n}}</li> {% endfor %} </ul> </div> <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script> <script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script> </body> </html>
5)執行觀察效果
➜ python run.py
效果如下:
可以看到,將模板中的 my_string、my_list[3] 替換掉了,並且用 for 迴圈語句,生成了一個 list。
模板通常利用繼承,繼承包括定義所有後續子模板基本結構的單個基礎模板。您可以使用標記 {% extends %}
和 {% block %}
來實現繼承。
這樣做的用例很簡單:隨著應用程式的增長,以及您繼續新增新模板,您將需要保持公共程式碼(如HTML導航欄、Javascript庫、CSS樣式表等)同步,這可能需要大量工作。使用繼承,我們可以將這些公共部分移動到父/基模板,這樣我們就可以建立或編輯這樣的程式碼一次,所有子模板都將繼承該程式碼。
注意:您應該總是儘可能多地向基本模板新增重複程式碼,以節省將來的時間,這將遠遠超過初始時間投資。
讓我們給我們的 DEMO 增加模板:
1)建立基礎模板(儲存為 layout.html
)
<!DOCTYPE html> <html> <head> <title>Flask Template Example</title> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <link href="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" media="screen"> <style type="text/css"> .container { max-width: 500px; padding-top: 100px; } h2 {color: red;} </style> </head> <body> <div class="container"> <h2>This is part of my base template</h2> <br> {% block content %}{% endblock %} <br> <h2>This is part of my base template</h2> </div> <script src="http://code.jquery.com/jquery-1.10.2.min.js"></script> <script src="http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script> </body> </html>
你注意到 {%block%}
標記了嗎?這定義了子模板可以填充的塊或區域。此外,也可實現覆蓋的作用。
2)用模板更新 template.html:
{% extends "layout.html" %} {% block content %} <h3> This is the start of my child template</h3> <br> <p>My string: {{my_string}}</p> <p>Value from the list: {{my_list[3]}}</p> <p>Loop through the list:</p> <ul> {% for n in my_list %} <li>{{n}}</li> {% endfor %} </ul> <h3> This is the end of my child template</h3> {% endblock %}
這樣 layout.html
模板中的 content 塊就會被 template.html
中的新定義給替換掉,最終效果如下:
那麼,我們就可以通過修改 layout.html
給其新增通用導航欄了:(將下列程式碼插入到 layout.html
的 <body>
標籤之後)
<nav class="navbar navbar-inverse" role="navigation"> <div class="container-fluid"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1"> <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="/">Jinja!</a> </div> <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1"> <ul class="nav navbar-nav"> <li class="active"><a href="#">Link</a></li> <li><a href="#">Link</a></li> </ul> <form class="navbar-form navbar-left" role="search"> <div class="form-group"> <input type="text" class="form-control" placeholder="Search"> </div> <button type="submit" class="btn btn-default">Submit</button> </form> <ul class="nav navbar-nav navbar-right"> <li><a href="#">Link</a></li> <li class="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <b class="caret"></b></a> <ul class="dropdown-menu"> <li><a href="#">Action</a></li> <li><a href="#">Another action</a></li> <li><a href="#">Something else here</a></li> <li class="divider"></li> <li><a href="#">Separated link</a></li> </ul> </li> </ul> </div><!-- /.navbar-collapse --> </div><!-- /.container-fluid --> </nav>
現在,從基礎擴充套件的每個子模板都將具有相同的導航欄。借用Java哲學的一句話:"Write once, use anywhere."
如果需要從基礎模板渲染塊,使用 super block:
{{ super() }}
給基礎模板增加一個頁尾:
<body> <div class="container"> ... <h2>This is part of my base template</h2> <br> <div class="footer"> {% block footer %} Watch! This will be added to my base and child templates using the super powerful super block! <br> <br> <br> {% endblock %} </div> </div> ...
此時,我們可以給 template.html
增加 super block,從而實現子模板複用父模板中的塊:
{% extends "layout.html" %} {% block content %} <h3> This is the start of my child template</h3> <br> <p>My string: {{my_string}}</p> <p>Value from the list: {{my_list[3]}}</p> <p>Loop through the list:</p> <ul> {% for n in my_list %} <li>{{n}}</li> {% endfor %} </ul> <h3> This is the end of my child template</h3> {% block footer %} {{super()}} {% endblock %} {% endblock %}
效果如下:
super block 用於模組共用父模組的 block,當然還有一些高階玩法,比如下面的例子:
父模板:
{% block heading %} <h1>{% block page %}{% endblock %} - Flask Super Example</h1> {% endblock %}
子模板:
{% block page %}Home{% endblock %} {% block heading %} {{ super() }} {% endblock %}
這樣當存取子模組時,會拼接一個 <h1>Home - Flask Super Example</h1>
欄位。發現沒,我們通過這樣的方法,實現了標題的繼承(有一定的繼承,也有一定的子模組自己的資訊)。
迴歸正軌,對於更新標題,我們這裡這樣設計(修改 template.html
中的兩行程式碼)
{% block title %}{{title}}{% endblock %} ... {% block page %}{{title}}{% endblock %}
這樣我們可以通過 python 進來直接修改標題了(修改 run.py
):
@app.route("/") def template_test(): return render_template( 'template.html', my_string="Wheeeee!", my_list=[0,1,2,3,4,5], title="Home")
在 Jinja 中,我們可以使用宏來抽象常用的程式碼段,這些程式碼段被反覆使用以避免重複。例如,通常會在導航欄上突出顯示當前頁面的連結(活動連結)。否則,我們必須使用 if/elif/else 語句來確定活動連結。使用宏,我們可以將這些程式碼抽象成一個單獨的檔案。
新增一個 macros.html
檔案:
{% macro nav_link(endpoint, name) %} {% if request.endpoint.endswith(endpoint) %} <li class="active"><a href="{{ url_for(endpoint) }}">{{name}}</a></li> {% else %} <li><a href="{{ url_for(endpoint) }}">{{name}}</a></li> {% endif %} {% endmacro %}
這裡,我們使用了 Flask 的 request object(Jinja 的預設一部分),用來檢查請求端點,然後將活動 class 分配給該端點。
使用基礎模板中的nav navbar nav類更新無序列表:
<ul class="nav navbar-nav"> {{ nav_link('home', 'Home') }} {{ nav_link('about', 'About') }} {{ nav_link('contact', 'Contact Us') }} </ul>
此外,請確保在模板頂部新增匯入:{% from "macros.html" import nav_link with context %}
最後,讓我們向控制器新增三個新端點:
@app.route("/home") def home(): return render_template( 'template.html', my_string="Wheeeee!", my_list=[0,1,2,3,4,5], title="Home") @app.route("/about") def about(): return render_template( 'template.html', my_string="Wheeeee!", my_list=[0,1,2,3,4,5], title="About") @app.route("/contact") def contact(): return render_template( 'template.html', my_string="Wheeeee!", my_list=[0,1,2,3,4,5], title="Contact Us")
重新整理頁面。測試頂部的連結。當前頁面是否突出顯示?(每次點選 Home, About, Contact Us,瀏覽器會自動跳轉到對應的 url,並載入頁面)
Jinja 使用過濾器修改變數,主要用於格式化目的。
這有個例子;
{{ num | round }}
這將使 num 變數四捨五入。因此,如果我們將引數 num=46.99 傳遞到模板中,那麼將輸出47.0。(把大括號中的語句當做 shell,就明白了,豎線是傳遞作用,round是個過濾器,這裡是所有的過濾器)
再來個例子:
{{ list|join(', ') }}
可以給 list 陣列中的變數加個逗號。
其實,除了自帶的過濾器,我們也可以自定義:
1)在 run.py 的所有函數前增加 app = Flask(__name__)
用於建立一個 app
2)增加一個 datetimefilter 函數,並將其註冊到 app 的過濾器
@app.template_filter() # 宣告,這是個過濾器 def datetimefilter(value, format='%Y/%m/%d %H:%M'): """Convert a datetime to a different format.""" return value.strftime(format) app.jinja_env.filters['datetimefilter'] = datetimefilter
3)這樣,我們在子模板中插入如下程式碼:
<h4>Current date/time: {{ current_time | datetimefilter }}</h4>
4)最後,只要在 python 中將時間傳入模板即可:
current_time = datetime.datetime.now()
5)效果如下:
這樣,就送大家快速入門了 Jinja,原始碼:https://github.com/mjhea0/thinkful-mentor/tree/master/python/jinja/flask_example
參考連結
[1]. 本文原始碼
[2]. Primer on Jinja Templating(本文翻譯並參考這篇)
[3]. Flask 官方檔案
[4]. 真正搞明白Python中Django和Flask框架的區別
[5]. Flask 主頁
[6]. 一個 Soft UI Dashboard - Free Jinja Template
[7]. Appseed 這個網站有很多 Flask 模板
[8]. Nginx 伺服器 SSL 證書安裝部署
[9]. python django web 開發 —— 15分鐘送到會用(只能送你到這了)
到此這篇關於python中的flask框架Jinja 模板入門的文章就介紹到這了,更多相關python flask Jinja 模板內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45