追溯到最初,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 。
整個請求的處理過程以下所示:
/
,所以調用對應的處理函數 hello()
hello()
函數的返回值,處理後返回給客戶端(瀏覽器)提示 在 Web 程序的語境下,雖然客戶端可能有多種類型,但在本書裏一般是指瀏覽器。
若是你把上面的程序保存成其餘的名字,好比 hello.py,接着執行 flask run
命令會返回一個錯誤提示。這是由於 Flask 默認會假設你把程序存儲在名爲 app.py 或 wsgi.py 的文件中。若是你使用了其餘名稱,就要設置系統環境變量 FLASK_APP
來告訴 Flask 你要啓動哪一個程序。
Flask 經過讀取這個文件對應的模塊尋找要運行的程序實例,你能夠把它設置成下面這些值:
如今在啓動 Flask 程序的時候,咱們一般要和兩個環境變量打交道:FLASK_APP
和 FLASK_ENV
。由於咱們的程序如今的名字是 app.py,暫時不須要設置 FLASK_APP
;FLASK_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">'複製代碼
保存修改後,只須要在瀏覽器裏刷新頁面,你就會看到頁面上的內容也會隨之變化。
另外,你也能夠自由修改傳入 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
# -*- coding: utf-8-*-
,並在包含中文的字符串前面添加 u
前綴。本書中對於包含中文的字符串均添加了 u
前綴,這在 Python 3 中並不須要。/user/<int:number>
會將 URL 中的 number 部分處理成整型,同時這個變量值接收傳入數字。url_for
函數)只能在特定的狀況下才能正確執行,好比視圖函數內。咱們先暫時不用糾結,後面再慢慢了解。.
開頭的文件默認會被隱藏,執行 ls
命令時會看不到它們,這時你可使用 ls -f
命令來列出全部文件。