第二天:在Flask Web應用中使用模板

原文: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/,查看結果:

clipboard.png

這樣應用就運行起來了。大家有沒有發現,如果我後面還想擴展其他功能,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代碼。

用同樣的方式運行程序,效果應用和沒有使用模板的情況是一樣的,如下圖

clipboard.png

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語句,效果如下圖所示:

clipboard.png

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,效果如下圖所示:

clipboard.png

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,效果如下圖所示:

clipboard.png

5. 總結

學習完第二天的教程,我們掌握瞭如下技能:

  1. 知道什麼是模板及爲什麼要使用模板
  2. 模板的基本用法
  3. 模板中如何使用條件語句
  4. 模板中如何使用循環語句
  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

clipboard.png

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章