FMTV F:form表單 M:Model模型(數據庫) T:Template模板 V:view視圖(路由)
模板是一個包含響應文本的文件,其中包含用佔位變量表示的動態部分,其具體值 只在請求的上下文中才能知道。 使用真實值替換變量,再返回最終獲得的響應字符 串,這一過程稱爲渲染。可使用 render_template() 方法來渲染模板。你須要作 的一切就是將模板名和你想做爲關鍵字的參數傳入模板的變量。 Flask 會在 templates 文件夾裏尋找模板。因此,若是你的應用是個模塊,這個文 件夾應該與模塊同級;若是它是一個包,那麼這個文件夾做爲包的子目錄: 模板:
/application.py /templates /hello.html
包:javascript
/application /__init__.py /templates /hello.html
【hello.html】 html
<h1>Hello World!</h1> from flask import render_template @app.route('/hellotemplate/') def hellotemplate(): return render_template('hello.html')
模板引擎
Flask使用了一個名爲 Jinja2 的強大模板引擎java
{% ... %} Jinja語句,例如判斷、循環語句jquery
{{ ... }} 變量,會顯示在瀏覽器中數據庫
{# ... #} 註釋,不會輸出到瀏覽器中flask
在模板中使用的 {{ name }} 結構表示一個變量,它是一種特殊的佔位符,告訴
模板引擎這個位置的值從渲染模板時使用的數據中獲取。
【helloname.html】 bootstrap
<h1>Hello, {{ name }}!</h1> @app.route('/hellotemplate/<name>') def helloname(name): return render_template('helloname.html',name = name)
可使用過濾器修改變量,過濾器名添加在變量名以後,中間使用豎線分隔。瀏覽器
一、條件控制語句
【if.html】網絡
{% if name %} hello, {{name}} {% else %} hello, world! {% endif %}
二、 for 循環
【for.html】app
<ol> {% for a in range(10) %} <li>a</li> {% endfor %} </ol> @app.route('/for/') def fortemplate(): return render_template('for.html')
三、Jinja2 還支持宏(macro) 。宏相似於 Python 代碼中的函數(def)。
【macro.html】
{% macro myprint(A) %} this is {{ A }} {% endmacro %} {{ myprint(A) }} @app.route('/macro/<a>') def macrotamplate(a): return render_template('macro.html',A = a)
爲了重複使用宏,咱們能夠將其保存在單獨的文件中,而後在須要使用的模板中導入:
【macro2.html】
{% from 'macro.html' import myprint %} {{ myprint(A) }} @app.route('/macro2/<a>') def macro2template(a): return render_template('macro2.html',A = a)
四、包含(include)
【include.html】
{% include 'macro.html' %} @app.route('/include/<a>') def includetemplate(a): return render_template('include.html',A = a)
【注意】
包含進來的文件裏的全部變量也包含進來了,須要在視圖函數中指定
首先,建立一個名爲 base.html 的基模板:
【base.html】
<html> <head> {% block head %} <title> {% block title %} {% endblock %} - My Application </title> {% endblock %} </head> <body> {% block body %} {% endblock %} </body> </html>
block 標籤訂義的元素可在衍生模板中修改。下面這個示例是基模板的衍生模板:
【extend.html】
% extends "base.html" %} {% block title %}Index{% endblock %} {% block head %} {{ super() }} <h1>super</h1> {% endblock %} {% block body %} <h1>Hello, World!</h1> {% endblock %}
extends 指令聲明這個模板衍生自 base.html。在 extends 指令以後,基模板中的 3個塊被從新定義,模板引擎會將其插入適當的位置。若是想添加內容到在父模板 內已經定義的塊,又不想失去父模板裏的內容,可使用super函數
Flask-Bootstrap 使用 pip安裝:
(venv) $ pip install flask-bootstrap
Flask 擴展通常都在建立程序實例後就初始化。
初始化 Flask-Bootstrap 以後,就能夠在程序中使用一個包含全部 Bootstrap 文件
的基模板。
【boootstrap.html】
{% extends "bootstrap/base.html" %} {% block title %}Flasky{% endblock %} {% block navbar %} <div class="navbar navbar-inverse" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <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="/">Flasky</a> </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li><a href="/">Home</a></li> </ul> </div> </div> </div> {% endblock %} {% block content %} <div class="container"> <div class="page-header"> <h1>Hello, {{ name }}!</h1> </div> </div> {% endblock %}
Jinja2 中的 extends 指令從 Flask-Bootstrap 中導入 bootstrap/base.html,從而 實現模板繼承。 Flask-Bootstrap 中的基模板提供了一個網頁框架,引入了 Bootstrap 中的全部 CSS 和JavaScript 文件。基模板中定義了可在衍生模板中重定義的塊。 block 和 endblock 指令定義的塊中的內容可添加到基模板中。 上面這個 boootstrap.html 模板定義了 3 個塊,分別名爲 title、 navbar 和 content。 這些塊都是基模板提供的, 可在衍生模板中從新定義。 title 塊的做用很明顯,其中 的內容會出如今渲染後的 HTML 文檔頭部,放在 <title> 標籤中。 navbar 和 content 這兩個塊分別表示頁面中的導航條和主體內容。在這個模板中, navbar 塊使用 Bootstrap 組件定義了一個簡單的導航條。content 塊中有個<div> 容器,其中包含一個頁面頭部。 以前版本的模板中的歡迎信息,如今就放在這個頁面頭部。
from flask_bootstrap import Bootstrap bootstrap = Bootstrap(app) @app.route('/bootstrap/<name>') def bootstraptemplate(name): return render_template('boootstrap.html',name = name)
【注意】
不少塊都是 Flask-Bootstrap 自用的,若是直接重定義可能會致使一些問題。例如,
Bootstrap 所需的文件在 styles 和 scripts 塊中聲明。若是程序須要向已經有內
容的塊中添加新內容,必須使用Jinja2 提供的 super() 函數。例如,若是要在衍生
模板中添加新的 JavaScript 文件,須要這麼定義 scripts 塊:
{% block scripts %} {{ super() }} <script type="text/javascript" src="my-script.js"></script> {% endblock %}
【templates/404.html】
<h1> Page is not Found </h1> @app.errorhandler(404) def page_not_found(e): return render_template('404.html'), 404
【templates/base.html: 包含導航條的程序基模板】
{% extends "bootstrap/base.html" %} {% block title %}Flasky{% endblock %} {% block head %} {{ super() }} <link rel="shortcut icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x -icon"> <link rel="icon" href="{{ url_for('static', filename='favicon.ico') }}" type="image/x -icon"> {% endblock %} {% block navbar %} <div class="navbar navbar-inverse" role="navigation"> <div class="container"> <div class="navbar-header"> <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse"> <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="/">Flasky</a> </div> <div class="navbar-collapse collapse"> <ul class="nav navbar-nav"> <li><a href="/">Home</a></li> </ul> </div> </div> </div> {% endblock %} {% block content %} <div class="container"> {% block page_content %}{% endblock %} </div> {% endblock %} {% block scripts %} {{ super() }} {{ moment.include_moment() }} {% endblock %}
這個模板的 content 塊中只有一個 <div> 容器,其中包含了一個名爲
page_content 的新的空塊,塊中的內容由衍生模板定義。
【templates/404.html:使用模板繼承機制自定義 404 錯誤頁面】
{% extends "base.html" %} {% block title %}Flasky - Page Not Found{% endblock %} {% block page_content %} <div class="page-header"> <h1>Not Found</h1> </div> {% endblock %}
templates/boootstrap.html 如今能夠經過繼承這個基模板來簡化內容:
【 templates/boootstrap.html: 使用模板繼承機制簡化頁面模板】
{% extends "base.html" %} {% block title %}Flasky{% endblock %} {% block page_content %} <div class="page-header"> <h1>Hello, {{ name }}!</h1> </div> {% endblock %}
默認設置下, Flask 在程序根目錄中名爲 static 的子目錄中尋找靜態文件。
若是須要,可在static 文件夾中使用子文件夾存放文件。給靜態文件生成
URL ,使用特殊的 'static' 端點名:
【westeros.html】
<img src = "{{url_for('static',filename = 'westeros.jpg')}}"> @app.route('/westeros/') def westeros(): return render_template('westeros.html')
這個文件應該存儲在文件系統上的 static/westeros.jpg 。
lask-Moment 是一個 Flask 程序擴展,能把moment.js 集成到 Jinja2 模
板中。 Flask-Moment 可使用 pip 安裝:
(venv) $ pip install flask-moment
這個擴展的初始化方法和Bootstrap同樣,以程序實例app爲參數:
from flask_moment import Moment moment = Moment(app)
除了 moment.js, Flask-Moment 還依賴 jquery.js。要在 HTML 文檔的某個
地方引入這兩個庫,能夠直接引入,這樣能夠選擇使用哪一個版本,也可以使用擴
展提供的輔助函數,從內容分發網絡(Content Delivery Network, CDN)中
引入經過測試的版本。 Bootstrap 已經引入了 jquery.js, 所以只需引入
moment.js便可。
【base.html中增長了】
{% block scripts %} {{ super() }} {{ moment.include_moment() }} {% endblock %}
【moment.html】
{% extends "base.html" %} {% block page_content %} <div class="page-header"> <h1>Hello World!</h1> </div> <p>The local date and time is {{moment(current_time).format('LLL')}}.</p> <p>That was {{moment(current_time).fromNow(refresh = true)}}.</p> {% endblock %}
把變量current_time 傳入模板進行渲染
from datetime import datetime @app.route('/moment/') def momenttemplate(): return render_template('moment.html',current_time = datetime.utcnow())