《Flask 入門教程》 第 2 章:Hello, Flask!

追溯到最初,Flask 誕生於 Armin Ronacher 在 2010 年愚人節開的一個玩笑。後來,它逐漸發展成爲一個成熟的 Python Web 框架,愈來愈受到開發者的喜好。目前它在 GitHub 上是 Star 數量最多的 Python Web 框架,沒有之一。python

Flask 是典型的微框架,做爲 Web 框架來講,它僅保留了核心功能:請求響應處理模板渲染。這兩類功能分別由 Werkzeug(WSGI 工具庫)完成和 Jinja(模板渲染庫)完成,由於 Flask 包裝了這兩個依賴,咱們暫時不用深刻了解它們。git

主頁

這一章的主要任務就是爲咱們的程序編寫一個簡單的主頁。主頁的 URL 通常就是根地址,即 /。當用戶訪問根地址的時候,咱們須要返回一行歡迎文字。這個任務只須要下面幾行代碼就能夠完成:github

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
    return 'Welcome to My Watchlist!'複製代碼

按照慣例,咱們把程序保存爲 app.py,確保當前目錄是項目的根目錄,而後在命令行窗口執行 flask run 命令啓動程序(按下 Control + C 能夠退出):django

$ flask run
* Serving Flask app "app.py"
* Environment: production
  WARNING: Do not use the development server in a production environment.
  Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)複製代碼

如今打開瀏覽器,訪問 http://localhost:5000 便可訪問咱們的程序主頁,並看到咱們在程序裏返回的問候語,以下圖所示:flask



執行 flask run 命令時,Flask 會使用內置的開發服務器來運行程序。這個服務器默認監聽本地機的 5000 端口,也就是說,咱們能夠經過在地址欄輸入 http://127.0.0.1:5000 或是 http://localhost:5000 訪問程序。瀏覽器

注意 內置的開發服務器只能用於開發時使用,部署上線的時候要換用性能更好的服務器,咱們會在最後一章學習。服務器

解剖時間

下面咱們來分解這個 Flask 程序,瞭解它的基本構成。app

首先咱們從 flask 包導入 Flask 類,經過實例化這個類,建立一個程序對象 app框架

from flask import Flask
app = Flask(__name__)複製代碼

接下來,咱們要註冊一個處理函數,這個函數是處理某個請求的處理函數,Flask 官方把它叫作視圖函數(view funciton),你能夠理解爲「請求處理函數」。編輯器

所謂的「註冊」,就是給這個函數戴上一個裝飾器帽子。咱們使用 app.route() 裝飾器來爲這個函數綁定對應的 URL,當用戶在瀏覽器訪問這個 URL 的時候,就會觸發這個函數,獲取返回值,並把返回值顯示到瀏覽器窗口:

@app.route('/')
def hello():
    return 'Welcome to My Watchlist!'複製代碼

填入 app.route() 裝飾器的第一個參數是 URL 規則字符串,這裏的 /指的是根地址。

咱們只須要寫出相對地址,主機地址、端口號等都不須要寫出。因此說,這裏的 / 對應的是主機名後面的路徑部分,完整 URL 就是 http://localhost:5000/。若是咱們這裏定義的 URL 規則是 /hello,那麼完整 URL 就是 http://localhost:5000/hello

整個請求的處理過程以下所示:

  1. 當用戶在瀏覽器地址欄訪問這個地址,在這裏即 http://localhost:5000/
  2. 服務器解析請求,發現請求 URL 匹配的 URL 規則是 /,所以調用對應的處理函數 hello()
  3. 獲取 hello() 函數的返回值,處理後返回給客戶端(瀏覽器)
  4. 瀏覽器接受響應,將其顯示在窗口上

提示 在 Web 程序的語境下,雖然客戶端可能有多種類型,但在本書裏一般是指瀏覽器。

程序發現機制

若是你把上面的程序保存成其餘的名字,好比 hello.py,接着執行 flask run 命令會返回一個錯誤提示。這是由於 Flask 默認會假設你把程序存儲在名爲 app.py 或 wsgi.py 的文件中。若是你使用了其餘名稱,就要設置系統環境變量 FLASK_APP 來告訴 Flask 你要啓動哪一個程序。

Flask 經過讀取這個文件對應的模塊尋找要運行的程序實例,你能夠把它設置成下面這些值:

  • 模塊名
  • Python 導入路徑
  • 文件目錄路徑

管理環境變量

如今在啓動 Flask 程序的時候,咱們一般要和兩個環境變量打交道:FLASK_APPFLASK_ENV。由於咱們的程序如今的名字是 app.py,暫時不須要設置 FLASK_APPFLASK_ENV 用來設置程序運行的環境,默認爲 production。在開發時,咱們須要開啓調試模式(debug mode)。調試模式能夠經過將系統環境變量 FLASK_ENV 設爲 development 來開啓。調試模式開啓後,當程序出錯,瀏覽器頁面上會顯示錯誤信息;代碼出現變更後,程序會自動重載。

爲了避免用每次打開新的終端會話都要設置環境變量,咱們安裝用來管理系統環境變量的 python-dotenv:

$ pipenv install python-dotenv複製代碼

當 python-dotenv 安裝後,Flask 會從項目根目錄的 .flaskenv 和 .env 文件讀取環境變量並設置。咱們分別使用文本編輯器建立這兩個文件,或是使用更方便的 touch 命令建立:

$ touch .env .flaskenv複製代碼

.flaskenv 用來存儲 Flask 命令行系統相關的公開環境變量;而 .env 則用來存儲敏感數據,不該該提交進Git倉庫,咱們把 .env 添加到 .gitignore 文件的結尾(新建一行)來讓 Git 忽略它。你可使用編輯器執行這個操做:

.env複製代碼

在新建立的 .flaskenv 文件裏,咱們寫入一行 FLASK_ENV=development ,將環境變量 FLASK_ENV 的值設爲 development,以便開啓調試模式:

FLASK_ENV=development複製代碼

實驗時間

在這個小節,咱們能夠經過作一些實驗,來擴展和加深對本節內容的理解。

修改視圖函數返回值

首先,你能夠自由修改視圖函數的返回值,好比:

@app.route('/')
def hello():
    return u'歡迎來到個人 Watchlist!'複製代碼

返回值做爲響應的主體,默認會被瀏覽器做爲 HTML 格式解析,因此咱們能夠添加一個 HTML 元素標記:

@app.route('/')
def hello():
    return '<h1>Hello Totoro!</h1><img src="http://helloflask.com/totoro.gif">'複製代碼

保存修改後,只須要在瀏覽器裏刷新頁面,你就會看到頁面上的內容也會隨之變化。



修改 URL 規則

另外,你也能夠自由修改傳入 app.route 裝飾器裏的 URL 規則字符串,但要注意以斜線 / 做爲開頭。好比:

@app.route('/home')
def hello():
    return 'Welcome to My Watchlist!'複製代碼

保存修改,這時刷新瀏覽器,則會看到一個 404 錯誤提示,提示頁面未找到(Page Not Found)。這是由於視圖函數的 URL 改爲了 /home,而咱們刷新後訪問的地址仍然是舊的 /。若是咱們把訪問地址改爲 http://localhost:5000/home,就會正確看到返回值。

一個視圖函數也能夠綁定多個 URL,這經過附加多個裝飾器實現,好比:

@app.route('/')
@app.route('/index')
@app.route('/home')
def hello():
    return 'Welcome to My Watchlist!'複製代碼

如今不管是訪問 http://localhost:5000/、http://localhost:5000/home 仍是 http://localhost:5000/index 均可以看到返回值。

在前面,咱們之因此把傳入 app.route 裝飾器的參數稱爲 URL 規則,是由於咱們也能夠在 URL 裏定義變量部分。好比下面這個視圖函數會處理全部相似 /user/<name> 的請求:

@app.route('/user/<name>')
def user_page():
    return 'User page'複製代碼

不論你訪問 http://localhost:5000/user/greyli,仍是 http://localhost:5000/user/peter,抑或是 http://localhost:5000/user/甲,都會觸發這個函數。經過下面的方式,咱們也能夠在視圖函數裏獲取到這個變量值:

@app.route('/user/<name>')
def user_page(name):
    return 'User: %s' % name複製代碼

修改視圖函數名?

最後一個能夠修改的部分就是視圖函數的名稱了。首先,視圖函數的名字是自由定義的,和 URL 規則無關。和定義其餘函數或變量同樣,只須要讓它表達出所要處理頁面的含義便可。

除此以外,它還有一個重要的做用:做爲表明某個路由的端點(endpoint),同時用來生成 URL。對於程序內的 URL,爲了不手寫,Flask 提供了一個 url_for 函數來生成 URL,它接受的第一個參數就是端點值,默認爲視圖函數的名稱:

from flask import url_for

...

@app.route('/')
def hello():
    return 'Hello'

@app.route('/user/<name>')
def user_page(name):
    return 'User: %s' % name

@app.route('/test')
def test_url_for():
    # 下面是一些調用示例:
    print(url_for('hello'))  # 輸出:/
    # 注意下面兩個調用是如何生成包含 URL 變量的 URL 的
    print(url_for('user_page', name='greyli'))  # 輸出:/user/greyli
    print(url_for('user_page', name='peter'))  # 輸出:/user/peter
    print(url_for('test_url_for'))  # 輸出:/test
    # 下面這個調用傳入了多餘的關鍵字參數,它們會被做爲查詢字符串附加到 URL 後面。
    print(url_for('test_url_for', num=2))  # 輸出:/test?num=2
    return 'Test page'複製代碼

實驗過程當中編寫的代碼能夠刪掉,也能夠保留,但記得爲根地址返回一行問候,這但是咱們這一章的任務。

本章小結

這一章咱們爲程序編寫了主頁,同時學習了 Flask 視圖函數的基本編寫方式。結束前,讓咱們提交代碼:

$ git add .
$ git commit -m "Add minimal home page"
$ git push複製代碼

爲了保持簡單,咱們統一在章節最後一次提交全部改動。在現實世界裏,一般會根據須要分爲多個 commit;一樣的,這裏使用 -m 參數給出簡單的提交信息。在現實世界裏,你可能須要撰寫更完整的提交信息。

提示 你能夠在 GitHub 上查看本書示例程序的對應 commit:016302a

進階提示

  • 若是你使用 Python 2.7,爲了使程序正常工做,須要在腳本首行添加編碼聲明 # -*- coding: utf-8-*- ,並在包含中文的字符串前面添加 u 前綴。本書中對於包含中文的字符串均添加了 u 前綴,這在 Python 3 中並不須要。
  • 對於 URL 變量,Flask 還支持在 URL 規則字符串裏對變量設置處理器,對變量進行預處理。好比 /user/<int:number> 會將 URL 中的 number 部分處理成整型,同時這個變量值接收傳入數字。
  • 由於 Flask 的上下文機制,有一些變量和函數(好比 url_for函數)只能在特定的狀況下才能正確執行,好比視圖函數內。咱們先暫時不用糾結,後面再慢慢了解。
  • 名字以 . 開頭的文件默認會被隱藏,執行 ls 命令時會看不到它們,這時你可使用 ls -f 命令來列出全部文件。
  • 瞭解 HTTP 基本知識將會有助於你瞭解 Flask 的工做原理。
  • 閱讀文章《互聯網是如何工做的》
  • 閱讀文章《從HTTP請求 - 響應循環探索Flask的基本工做方式》
  • 若是你是《Flask Web 開發實戰》的讀者,這部分的進階內容能夠在第 1 章《初識 Flask》和第 2 章《HTTP 和 Flask》找到。
相關文章
相關標籤/搜索