文章插圖

文章插圖
一、概述
在第二部分中 , 我將討論如何使用模板 。
學習完第一章之后 , 你已經擁有了一個雖然簡單 , 但是可以成功運行Web應用 , 它的文件結構如下:
microblogvenvapp__init__.pyroutes.pymicroblog.py在終端會話中設置環境變量FLASK_APP=microblog.py , 然后執行flask run命令來運行應用 。包含這個應用的Web服務啟動之后 , 你可以通過在Web瀏覽器的地址欄中鍵入URL http://localhost:5000/ 來驗證 。本章將沿用這個應用 , 在此之上 , 你將學習如何生成包含復雜結構和諸多動態組件的網頁 。如果對這個應用和相關開發流程有所遺忘 , 請回顧第一章 。
二、什么是模板?
我設計的微博應用程序的主頁會有一個歡迎用戶的標題 。雖然目前的應用程序還沒有實現用戶概念 , 但這不妨礙我使用一個Python字典來模擬一個用戶 , 如下所示:
user = {'username':'Miguel'}創建模擬對象是一項實用的技術 , 它可以讓你專注于應用程序的一部分 , 而無需為系統中尚不存在的其他部分分心 。在設計應用程序主頁的時候 , 我可不希望因為沒有一個用戶系統來分散我的注意力 , 因此我使用了模擬用戶對象 , 來繼續接下來的工作 。原先的視圖函數返回簡單的字符串 , 我現在要將其擴展為包含完整HTML頁面元素的字符串 , 如下所示:
from app import app @app.route('/')@app.route('/index')def index():user = {'username': 'Miguel'}return '''<html><head><title>Home Page - Microblog</title></head><body><h1>Hello, ''' + user['username'] + '''!</h1></body></html>運行flask run 更新視圖功能 , 并查看應用程序在瀏覽器中的顯示效果 。如果我說這個函數返回HTML的方式并不友好的話 , 你可能會覺得詫異 。設想一下 , 當這個視圖函數中的用戶和博客不斷變化時 , 里面的代碼將會變得多么的復雜 。應用的視圖函數及其關聯的URL也會持續增長 。如果哪天我決定更改這個應用的布局 , 那就不得不更新每個視圖函數的HTML字符串 。顯然 , 隨著應用的擴張 , 這種方式完全不可行 。
將應用程序的后臺邏輯和網頁布局劃分開來 , 你不覺得更容易組織管理嗎?甚至你可以聘請一位Web設計師來設計一個殺手級的網站前端 , 而你只需要用Python編寫后臺應用邏輯 。
模板有助于實現頁面展現和業務邏輯之間的分離 。在Flask中 , 模板被編寫為單獨的文件 , 存儲在應用程序包內的templates文件夾中 。在確定你在microblog目錄后 , 創建一個存儲模板的目錄:
在Flask中 , 模板是作為單獨的文件編寫的 , 存放在應用程序 包內的 templates文件夾(約定俗成命名為 templates)下 。
即在app目錄下創建templates文件夾:
# mkdir templates在下面可以看到你的第一個模板 , 它的功能與上面的index()視圖函數返回的HTML頁面相似 。把這個文件寫在app/templates/index.html中:<html><head><title>{{ title }} - Microblog</title></head><body><h1>Hello, {{ user.username }}!</h1></body></html>這是一個標準的、簡單的HTML頁面 。但有一點跟我們寫HTML代碼不同是title標簽、h1標簽中的 {{ … }}兩對花括號 , 在此它是個 占位符 , 作用是將表達式(如文字、數學式子、比較運算符等 , 其實在Python中是一個Python語句)打印到模板進行輸出 。具體參考Jinja2官網文檔 。這些占位符表示HTML頁面中可變的部分 , 并且只在運行時才知道 。這個HTML頁面看起來非常簡單 , 唯一值得關注的地方是{{ … }} 。{{ … }}包含的內容是動態的 , 只有在運行時才知道具體表示成什么樣子 。
網頁渲染轉移到HTML模板之后 , 視圖函數就能被簡化:現在HTML頁面的呈現已在HTML模板中了 , 這樣接著就可簡化一下視圖函數index()了 。修改routes.py文件app/routes.py:使用render_template()函數
from app import appfrom flask import render_template#從flask包中導入render_template函數@app.route('/')@app.route('/index')def index():user = {'username':'Miguel'}return render_template('index.html', title='Home', user=user)將模板(index.html)轉換為完整HTML頁面的操作稱之為 呈現(render , 譯作 遞交、表達、給予 , 在此譯作 “渲染”) 。為了渲染模板 , 由從flask包中導入的render_template()完成 , 此函數“攜帶”模板文件名(index.html)、模板參數的變量列表 , 并返回相同的模板 , 不過其中所有占位符都替換為實際值 。看起來好多了吧? 趕緊試試這個新版本的應用程序 , 看看模板是如何工作的 。在瀏覽器中加載頁面后 , 你需要從瀏覽器查看HTML源代碼并將其與原始模板進行比較 。
render_template()函數調用Flask框架原生依賴的Jinja2模板引擎 。Jinja2用render_template()函數傳入的參數中的相應值替換{{…}}塊 。
控制結構—-if條件、for循環、繼承
上述過程只是理解了:Jinja2模板引擎 如何在渲染過程中用實際值 替換 (模板中的)占位符 。接下來將認識到更多 Jinja2在模板文件中支持的更多強大操作:if條件、for循環、繼承等 。源自官網的這句話:
There are a few kinds of delimiters. The default Jinja delimiters are configured as follows: {% ... %} for Statements{{ ... }} for Expressions to print to the template output{# ... #} for Comments not included in the template output#... ## for Line Statementsif、for、繼承均在{% … %}塊中寫控制語句 。if條件形如:{% if title %}...語句塊{% else %}...語句塊{% endif %}【flask web開發實戰 入門 pdf Flask Web開發:基于Python的Web應用開發實戰】app/templates/index.html:模板中添加條件語句<html><head>{% if title %}<title>{{ title }} - Microblog</title>{% else %}<title>Welcome to Microblog!</title>{% endif %}</head><body><h1>Hello,{{ user.username }}!</h1></body></html>上述代碼中if語句塊的功能是:若視圖函數index()沒有傳遞title占位符變量的值 , 則index.html模板將會提供默認值(else語句塊中) , 而不是顯示空標題 。嘗試將routes.py中render_template()中的title=’Home’,刪除 。效果:圖略for循環在模板中形如:
{% for post in posts %}...語句塊{% endfor %}需求:登錄用戶可在主頁中查看最新的帖子 。實現:首先 , 用虛擬對象的方法來創建一些用戶、帖子 , 以供顯示 。app/routes.py:視圖函數中的假帖子from app import appfrom flask import render_template#從flask包中導入render_template函數 @app.route('/')@app.route('/index')def index():user = {'username':'Miguel'}#用戶posts = [#創建一個列表:帖子 。里面元素是兩個字典 , 每個字典里元素還是字典 , 分別作者、帖子內容 。{'author': {'username':'John'},'body':'Beautiful day in Portland!'} , {'author': {'username':'Susan'},'body':'The Avengers movie was so cool!'} ]return render_template('index.html', title='Home', user=user, posts=posts)帖子列表 可包含任意數量的元素 , 由視圖函數index()決定將在頁面中顯示的帖子數量 。而模板index.html不能假設這有多少個帖子 , 因此它需要準備好以通用方式呈現視圖發送來的盡可能多的帖子 。在模板index.html中 , 用for循環遍歷所有的帖子并呈現 。app/templates/index.html:在模板中的for循環<html><head>{% if title %}<title>{{ title }} - Microblog</title>{% else %}<title>Welcome to Microblog!</title>{% endif %}</head><body><h1>Hello,{{ user.username }}!</h1>{% for post in posts %}<div><p>{{ post.author.username }} says: <b>{{ post.body }}</b></p></div>{% endfor %}</body></html>模板繼承形如:{% extends "base.html" %} {% block content %}...{% endblock %}現在 , 大部分Web應用程序在頁面頂部有一個導航欄 , 它常包含一些常用鏈接:如登錄、退出、編輯個人資料等 。可以很輕松地將導航欄添加到index.html模板 , 甚至更多的HTML頁面中 。但隨著應用程序的增長(頁面數量的增多) , 這些頁面都將使用相同的導航欄 , 不可能每一個頁面都增加一份相同的導航欄代碼 。Jinja2具有模板繼承功能 , 完美解決上述問題 。在實際操作中 , 將所有模板共有的頁面布局部分移至基礎模板中 , 其他模板則繼承自它 。
實例:實現一個簡單的導航欄 , 其他模板繼承它 。在app/templates目錄下創建一個基礎模板文件 base.html 。app/templates/base.html:帶導航欄的基礎模板
<html><head>{% if title %}<title>{{ title }} - Microblog</title>{% else %}<title>Welcome to Microblog</title>{% endif %}</head><body><div>Microblog:<a >Home</a></div><hr>{% block content %}{% endblock %}</body> </html>在上述基礎模板中 , 塊block 控制語句用于定義派生模板可自行插入的位置 。塊block 被賦予唯一的名字 content , 派生模板在提供其內容時可引用這個名稱 。修改index.html這個模板 , 讓其繼承base.html模板 。app/templates/index.html:從基礎模板繼承
{% extends "base.html" %} {% block content %}<h1>Hello,{{ user.username }}!</h1>{% for post in posts %}<div><p>{{ post.author.username }} says: <b>{{ post.body }}</b></p></div>{% endfor %}{% endblock %}base.html基礎模板 實現處理常規頁面的結構 , 則派生模板index.html簡化大部分內容 。extends語句 建立了兩個模板之間的繼承關系 , 因此 , Jinja2就會知道:當它被要求渲染index.html時 , 需要將其嵌入base.html中 。這倆模板具有匹配的block語句 名稱content , 這就是Jinja2如何將兩個模板合并為一個模板的方法 。目前為止 , 項目結構:
microblog/venv/app/templates/base.htmlindex.html__init__.pyroutes.pymicroblog.py
- c語言用什么工具開發 C語言的開發工具
- 日志框架有哪些 java開發日志規范
- 一碼通 西安 西安一碼通誰開發的
- javaweb項目開發案例精粹視頻 javaweb項目開發案例pdf精粹
- fc游戲模擬器下載手機版 FC游戲模擬器下載
- asp制作網站教程 ASP網站開發實用教程
- 商城系統源碼開發軟件 商城系統開發源碼
- 安卓中表格布局方法 安卓開發里表格布局怎么建立
- 火狐是中國的瀏覽器嗎 火狐瀏覽器誰開發的
- linux搭建web服務器的步驟 linux下安裝web服務器
