原文:http://www.catonlinepy.tech/
聲明:原創不易,未經許可,不得轉載
1. 你將學會什麼
通過學習第二天的內容,你將會對模板有所瞭解,並且知道爲什麼要使用模板,以及使用模板有什麼好處。這一天的學習內容涉及到的代碼都會託管到github上,貓姐再次強調,在學習本課內容時一定要自己嘗試手敲代碼,遇到問題再到github上去查看代碼,如果實在不知道如何去解決問題,可以在日誌下面留言說明具體情況。
2. 什麼是模板
視圖函數主要有兩個作用,一個是處理業務邏輯,另一個是給用戶返回相關內容。在大型應用中,如果把業務邏輯和返回響應內容放在一起的話,這樣會增加代碼的複雜度,並且也不好維護。所以模板它就承擔了視圖函數的另外一個作用:返回響應內容。這樣就可以實現業務邏輯和響應內容的分離,將所有的html代碼都存放到模板中,而視圖函數中只需要專心處理好業務邏輯即可。
下面貓姐通過一個簡單的例子來展示爲什麼要引入模板,以下是這個例子的代碼組織結構:
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary$ tree
.
├── day2
│ ├── run.py
│ └── template_demo
│ ├── __init__.py
│ └── routes.py
└── README.md
首先來建立第二天的代碼目錄,與第一天的課程類似,先激活虛擬環境miao_venv,創建方法都是一樣的:
# 進入到虛擬環境目錄,激活虛擬環境
maojie@Thinkpad:~/flask-plan/$source miao_venv/bin/activate
# 再到flask-course-primary目錄下創建第二天的課程day2目錄
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary$ mkdir day2
# 進入day2目錄
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary$ cd day2
# 新建template_demo目錄
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2$ mkdir template_demo
# 進入到template_demo目錄
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2$ cd template_demo/
# 在template_demo目錄中新建__init__.py文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2/template_demo$ touch __init__.py
# 在template_demo包中新建routes.py路由文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2/template_demo$ touch routes.py
# 在day2目錄下新建run.py文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2/$ touch run.py
在template_demo包的__init__.py中輸入如下代碼:
# 以下是__init__.py文件中的代碼,我們逐行進行解釋
from flask import Flask # 從flask包中導入Flask類
app = Flask(__name__) # 通過Flask類創建一個app實例
from template_demo import routes # 從template_demo包中導入routes文件裏的所有代碼
在routes.py文件中輸入如下代碼,包括響應內容中的HTML代碼:
# 從template_demo包中導入app實例
from template_demo import app
@app.route('/')
def index():
user = {'username':'貓姐'} # 建立一個user字典
# 返回HTML格式的響應內容
return '''
<html>
<head>
<title>Home Page-模板的使用-喵星在線</title>
</head>
<body>
<h1>Hello,''' + user['username'] + '''!</h1>
</body>
</html>'''
在第一課中,視圖函數返回的字符串是“你好,喵星在線”,而今天的課程,通過擴展,return 語句中呈現了完整的HTML代碼。如果大家對HTML語言不熟悉,可以在w3school在線教程中進行學習。
最後在day2目錄下run.py文件中輸入如下代碼:
from template_demo import app # 從template_demo包中導入app實例
if __name__ == "__main__":
app.run(debug=True) # app實例調用自己的run函數
# 解釋:debug=True,每次代碼有改動時,後臺會自動檢測到,避免自己每次停止、重啓後臺程序
用第一課運行程序的方法(python run.py),將程序運行起來,然後在瀏覽器中打開網址 http://localhost:5000/,查看結果:
這樣應用就運行起來了。大家有沒有發現,如果我後面還想擴展其他功能,index視圖函數裏面的代碼也會相應的變多,並且應用的視圖函數和關聯的URL也會相應的增加。如果我還想將HTML裏面的佈局更改一下的話,那我不得不更改每個視圖函數裏面的HTML標籤,這樣是不利於長久管理以及應用的擴張。
所以,這裏就出來了模板的概念,模板有助於實現業務邏輯和響應內容之間的分離,是實際項目開發中必須使用的一個技術。在Flask中,模板文件(即html文件)需要單獨存放在包內的templates目錄下。
3. 使用模板
在template_demo包中新建templates目錄,用來存放模板文件:
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2/template_demo$ mkdir templates
創建模板文件index.html,並輸入HTML代碼:
# 創建模板文件index.html (下面是使用touch命令創建的,大家也可以在ide集成開發環境中創建該文件)
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2/template_demo/templates$ touch index.html
# 在index.html中輸入如下代碼,這裏title,html_user變量是從視圖函數中傳進來的
<html>
<head>
<title>{{ title }}-模板的使用-喵星在線</title>
</head>
<body>
<h1>Hello,{{ html_user.username }}!</h1>
</body>
</html>
在上面的HTML代碼中,唯一值得關注的就是{{ ... }}裏面的內容,這些變量都是從視圖函數中傳遞進來的。
要渲染模板文件,還需要從Flask框架中導入render_template()這個函數,如下:
# 在routes.py文件中,從flask庫中導入render_template類
from flask import render_template
在視圖函數中調用render_template時,需要傳入模板的文件名以及模板參數的變量列表。視圖函數中進行如下操作,便可使用模板了:
# routes.py文件中輸入如下代碼
from flask import render_template # 從flask庫中導入render_template對象
from template_demo import app # 從template_demo包中導入app實例
@app.route('/')
def index():
user = {'username':'貓姐'} # 建立一個user字典
return render_template('index.html', title='HomePage', html_user=user)
在render_template函數中,index.html表示的是模板的文件名。title,html_user表示在模板文件中需要使用的變量。user表示是視圖函數中的user變量,user變量賦值給html_user變量,在模板中渲染的就是user變量的值了。這樣,routes.py文件中的代碼就好看多了,從而就實現了業務代碼和前端html代碼分離的效果,而且也更便於管理日後越發複雜的html代碼。
用同樣的方式運行程序,效果應用和沒有使用模板的情況是一樣的,如下圖
4. 模板的其它知識點
下面我們介紹一下模板的其它常用知識點,主要包括模板中if條件語句的使用,for循環語句的使用以及模板的繼承方法。
4.1 模板中的if條件語句的使用
說到模板中的條件語句,這裏不得不說說Jinja2的概念。它是python下被廣泛應用的模板引擎,是一種被設計自動生成文檔的簡單格式。在模板語言中,需要把變量傳給模板,然後替換成模板特定位置上的佔位變量名。它的使用方法很簡單,需要用到兩對大的花括號,{{ ... }},它裏面傳入的是變量名。
而Jinja2的條件語句,使用方法也很簡單,它用到的是一對花括號,裏面再加兩個百分號,像這樣{% %}。然後裏面可以寫if,else,for等,但是以if,for開頭,必須有閉合if,for的標籤。如下所示:
# jinja2中 if控制語句的使用
{% if title %}
{{ ... }}
{% else %}
{{ ... }}
{% endfor %}
# jinja2中 for控制語句的使用
{% for i in username %}
{{ ... }}
{% endfor %}
下面是在模板index.html文件添加一個條件語句的示例:
<html>
<head>
{% if title %}
<title>{{ title }} -模板的使用-喵星在線</title>
{% else %}
<title>模板的使用-喵星在線</title>
{% endif %}
</head>
<body>
<h1>Hello, {{ html_user.username }}!</h1>
</body>
</html>
如果視圖函數給模板傳遞了title參數,那麼它就會走if語句,如果沒有傳遞參數,則會走else語句,而不是顯示一個空的標題。在本例中,沒有給render_template函數的title參數傳入值,所以它會走else語句,效果如下圖所示:
4.2 模板中的循環
要理解Jinja2中是如何在模板中使用循環的,我們可以在路由函數中增加一些其它的信息,如下面使用posts列表變量保存了一些假的日誌信息,並將posts變量傳遞給了模板文件中將使用的htm_posts變量:
from flask import render_template
from template_demo import app
@app.route('/')
def index():
user = {'username': '貓姐'}
# 日誌由一個列表組成,其中裏面包含兩個字典,裏面各有author和content字段
posts = [
{
'author': {'username': '貓姐'},
'content': 'This day is Beautiful day!'
},
{
'author': {'username': '貓哥'},
'content': 'The flower is beautiful!'
}
]
return render_template('index.html', title='HomePage', html_user=user, html_posts=posts)
在index.html模板文件中,通過上面介紹的for循環語法,完成對htm_posts列表變量中每一篇日誌的渲染:
<!DOCTYPE html>
<html lang="en">
<head>
{% if title %}
<title>{{ title }} -模板的使用-喵星在線</title>
{% else %}
<title>模板的使用-喵星在線</title>
{% endif %}
</head>
<body>
<h1>Hello, {{ html_user.username }}!</h1>
{% for post in html_posts %} <!--for循環開始-->
<div>
<p>
{{ post.author.username }} says:<b>{{ post.content }}</b>
</p>
</div>
{% endfor %} <!-- for循環結束-->
</body>
</html>
打開瀏覽器URL,效果如下圖所示:
4.3 模板的繼承
我們在寫一個web應用時,隨着裏面的功能增多,代碼也會相應的變多,這時可能會有一些重複的HTML代碼,爲了去除大量重複的代碼,這時候出現了模板繼承的概念。它也是Jinja2的特性,它的特點就是將模板中相同的部分代碼轉移到一個基模板中,後面其它模板要使用的時候,只需要繼承基模板就可以了。
在template_demo/templates目錄下,新建layout.html文件,然後在layout.html中寫入如下代碼:
# 在templates目錄下新建layout.html文件
(miao_venv) maojie@Thinkpad:~/flask-plan/flask-course-primary/day2/templates$ touch layout.html
# layout.html文件中寫入如下代碼:
<html>
<head>
{% if title %}
<title>{{ title }} - 模板的使用-喵星在線</title>
{% else %}
<title>模板的使用-喵星在線</title>
{% endif %}
</head>
<body>
{% block content %}
{% endblock %}
</body>
</html>
在這個layout.html模板中,使用block控制塊來確定子模板插入代碼的位置。子模板通過引用block可以在裏面添加自己想要的內容。
下面index.html文件,可以直接繼承layout.html文件中的內容,而無需重複實現這段代碼,這樣在可以簡化index.html裏面的內容:
# index.html中改爲如下內容
{% extends "layout.html" %} # 繼承基模板裏面的內容
{% block content %} # 重新填寫content塊的內容
<h1>Hi, {{ html_user.username }}!</h1>
{% for post in html_posts %}
<div>
<p>{{ post.author.username }} says: <b>{{ post.content }}</b></p>
</div>
{% endfor %}
{% endblock %}
打開瀏覽器的URL,效果如下圖所示:
5. 總結
學習完第二天的教程,我們掌握瞭如下技能:
- 知道什麼是模板及爲什麼要使用模板
- 模板的基本用法
- 模板中如何使用條件語句
- 模板中如何使用循環語句
- 模板中如何繼承基模板
第三天的內容,我們將會帶領大家一起了解什麼是表單,表單如何創建,第二天的內容就到這裏,喜歡的同學們可以在下面點贊留言,或是訪問我的博客地址:http://www.catonlinepy.tech/ 加入我們的QQ羣進一步交流學習!
6. 代碼的獲取
大家可以到github上獲取今天教程中的所有代碼:https://github.com/miaojie19/...
具體下載代碼的命令如下:
# 使用git命令下載flask-course-primary倉庫所有的代碼
git clone https://github.com/miaojie19/flask-course-primary.git
# 下載完成後,進入day2目錄下面,即可看到今天的代碼
cd flask-course-primary
cd day2