第一章
1.1 Hello,Flask!
app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return '<h1>Hello Flask!</h1>'
1.1.1 創建示例程序
? 我們安裝Flask時,他會在Python解釋器中創建一個flask包,我們可以通過flask包的構造文件導入所有開放的類和函數。我們先從flask包中導入Flask類,這個類代表一個Flask程序。實例化這個類,就得到我們的程序實例app:
from flask import Flask
app = Flask(__name__)
? 傳入Flask構造方法的第一個參數是模塊或者包的名稱,我們應該使用特殊變量 __ name __. __
? Python會根據所處的模塊來賦予 __ name __變量相應的值,對于我們程序來說,這個值為app
1.1.2 注冊路由
? 在一個Web應用中,客戶端和服務器上的Flask程序的交互可以簡單概括為以下幾步:
? 1)用戶在瀏覽器輸入URL訪問某個資源
? 2)Flask接收用戶的請求并分析請求的URL
? 3)為這個URL找到對應的處理函數
? 4)執行函數并生成響應,返回給瀏覽器
? 5)瀏覽器接收并解析響應,將信息顯示在頁面中
? 在上面這些步驟中,大部分由Flask完成。我們需要做的只是建立處理請求的函數,并為其定義對應的URL規則。只需為函數附加app.route()裝飾器,并傳入URL規則作為參數,我們就可以讓URL與函數建立關聯。這個過程我們稱為注冊路由(route),路由負責管理URL和函數之間的映射,而這個函數則被成為視圖函數(view function)
-
路由的含義可以從字面理解,作為動詞時,他的含義是“按某路線發送”,即調用與請求URL對應的試圖函數。
在這個程序中,app.route()裝飾器把根地址/和index()函數綁定起來,當用戶訪問這個URL時就會觸發index()函數。視圖函數index()返回一行問候
@app.route('/') def index(): return '<h1>Hello, World!</h1>'
route()裝飾器的第一個參數是URL規則,用字符串表示,必須以/開始。這里的URL是相對的URL(又稱內部URL),即不包含域名的URL,以域名www.baidu.com為例,“/”對應的是根地址,即www.baidu.com,如果把URL規則改為“/hello”,則實際的絕對地址為www.baidu.com/hello
為視圖綁定多個URL
一個視圖函數可以綁定多個URL。比如下面的代碼把/hi和/hello都綁定到say_hello()函數上,著就會為say_hello()視圖注冊兩個路由,當用戶訪問這兩個URL中的任意一個,均會觸發say_hello()函數
@app.route('/hi') @app.route('/hello') def say_hello(): return '<h1>Hello, Flask!</h1>'
動態函數
我們不僅可以為視圖函數綁定多個URL,還可以在URL規則中添加變量部分,使用“<"變量名>"的形式表示。Flask處理請求時會把變量傳入視圖函數,所以我們可以添加承諾書獲取這個變量值。視圖函數greet(),他的URL規則包含一個name變量
@app.route('/greet/<name>') def greet(name): return '<h1>Hello, %s!</h1>' % name
因為URL中可以包含變量,所以將傳入app.route()字符串成為URL規則,而不是URL,Flask會解析請求并把請求的URL與視圖函數的URL規則進行匹配。比如,這個greet視圖URL規則為/greet/<name>,那么類似greet/foo、greet/bar的請求都會觸發這個視圖函數
當URL規則中包含變量時,如果用戶訪問URL中沒有添加變量,比如/greet,那么Flask在匹配失敗后會返回一個404錯誤響應。一個很常見的行為實在app.route()裝飾器使用defaults參數設置URL變量的默認值,這個參數接收字典作為輸入,存儲在URL變量和默認值的映射。在下面的代碼中,我們為greet視圖新添加了一個app.route()裝飾器,為/greet設置了默認的name值:
@app.route('/greet',defaults={'name':'Programmer'}) @app.route('/greet/<name>') def greet(name): return "<h1>Hello, %s</h1>" % name
這時如果用戶訪問/greet,那么變量name會使用默認值Programmer。視圖函數返回<h1>Hello, Programmer!</h1>
實際效果等同于:
1.2 啟動開發服務器
1.2.1 Run,Flask, Run!
? Flask通過依賴包Click內置了一個CLI(命令行交互界面),當我們安裝Flask后,會自動添加一個flask命令腳本,我們可以通過flask命令執行內置命令,擴展提供的命令或者我們自定義的命令。其中flask Run命令用來啟動內的開發服務器
-
flask run
執行flask --help查看所有可用的命令
-
如果執行flask run命令后顯示命令未找到提示(command found)或顯示其他錯誤,可以嘗試使用python -m flask run命令嘗試解決
flask run命令運行的開發服務器默認監聽http:// 127.0.0.1:5000/地址并開啟多線程支持。
自動發現程序實例
一般來說,執行flask run命令運行程序前,我們需要提供程序實例所在模塊的位置。我們在上面可以直接運行程序,因為Flask會自動探測程序實例,自動探測存在下面這些規則
- 從當前目錄尋找app.py和wsgi.py模塊,并從中尋找名為app或application的程序實例。
- 從環境變量FLASK_APP對應的值尋找名為app或application的程序實例
因為我們程序主模塊命名為app.py,所以flask run命令會自動在其中尋找程序實例。如果你的程序主模塊是其他名稱,比如hello.py,那么需要設置環境變量FLASK_APP,將包含程序實例的模塊名賦值給這個變量,Linux或macOS系統使用export命令:
export FLASK_APP = hello
在windows中使用set命令
set FLASK_APP = hello
管理環境變量
創建.env和.flaskenv文件管理環境變量
- .flaskenv文件用來存儲和Flask相關的公共環境變量
- .env用來存儲包含敏感信息的環境變量
使用方式如下所示:
SOME_VAR = 1
這是注釋
FOO='BAR'
1.2.2 更多啟動選項
使服務器外部可見
? 我們在上面啟動的Web服務器默認是對外不可見的,可以在run命令后田間 --host 選項將主機地址設為0.0.0.0使其對外可見:
- flask run --host=0.0.0.0
這會讓服務器監聽所有外部請求,個人計算機一般沒有公網IP,所以,你的程序只能被局域網內的其他用戶通過你的個人計算機的內網ip訪問,比如,你的內網ip為192.168.31.1,當局域網內的其他用戶訪問192.168.31.1:5000時,也會看到瀏覽器顯示內容
改變默認端口
Flask提供的Web服務器會默認監聽5000端口,你可以在啟動時傳入參數來改變他:
- flask run --port=8000
1.2.3 設置運行環境
? 開發環境:
? 指我們在本地編寫和測試程序時的計算機環境
? 生產環境 :
? 網站部署上線供用戶訪問時的服務器環境
? 根據運行環境的不同,Flask程序、擴展以及其他程序會改變相應的行為和設置。為了區分程序運行環境,Flask提供了一個FLASK_ENV環境變量用來設置環境,默認為production(生產)。在開發時,我們可以將其設為development(開發),這會開啟所有支持開發的特性。為了方便管理,我們將把環境變量FLASK_ENV的值寫入.flskenv文件中:
? FLASK_ENV = development
1.3 項目配置
? 在很多情況下,你需要設置程序的某些行為,這時你就需要使用配置變量。在Flask中。配置變量就是一些大寫形式的Python變量,你也可以稱之為配置參數或配置建。使用統一的配置變量可以避免在程序中以硬編碼的形式設置程序
? 加載配置方式一:
app.config['ADMIN_NAME'] = 'Perter'
-
配置的名稱必須是全大寫形式,小寫的變量將不會被加載、讀取
加載配置方式二:
app.config.update(
TESTION=True,
SECRET_KEY = 'sdfrgghjjkh7r'
)
? 加載配置方式三:從config字典里通過將配置變量的名稱作為鍵讀取對應的值
value = app.config['ADMIN_NAME]
1.4 URL與端點
? 在Web程序中,URL無處不在。如果程序中的URL都是以硬編碼的方式寫出,那么將會大大降低代碼的易用性。比如當你修改了某個路由的URL規則,那么程序里對應的url都要一個個修改,
? 更好的解決方法是使用Flask使用的url_for()獲取URL,當路由中定義的URL規則被修改時,這個函數會返回正確的URl
? 調用url_for()函數時,第一個參數為端點值。在Flask中,端點用來標記一個視圖函數以及對應的URL規則。端點的默認值為視圖函數的名稱。
? 例如下面的函數:
@app.route('/')
def index():
return 'Hello Flask!'
? 這個路由的端點即視圖函數的名稱index,調用url_for('index'),即可獲取對應的URL,即(‘/’)
-
在app.route()裝飾器中使用endpoint參數可以自定義端點值,不過我們一般不建議這樣使用
如果URL含有動態部分,那么我們需要在url_for()函數中傳入相應的參數,以下面的函數為例:
@app.route('/hello/<name>')
def greet(name):
return 'hello %s!' % name
? 這時使用url_for('say_hello',name="Jack")得到的URL為‘/hello/Jack’
1.5 Flask命令
? 除了Flask內置的flask run等命令,我們也可以自定義命令。在虛擬環境安裝flask后,包含許多內置命令的flsk就可以使用了。
? 通過創建一個函數,并為其添加app.cli.command()裝飾器,我們就可以注冊一個新的命令。如下所示
@app.cli.command()
def hello():
click.echo('hello, Human!')
? 函數的名稱即為命令名稱,這里注冊的命令即hello,你可以使用flask hello命令來觸發。作為替代,你也可以在app.cli.command()裝飾器中傳入參數設置命令名稱,比如app.cli.command('say-hello')會把命令名稱設置為say-hello,完整的命令即flask say-hello
? 借助click模塊的flask --help可以查看Flask提供的命令幫助文檔,我們自定義的hello命令也會出現在輸出命令列表中
1.6 模板與靜態文件
? 我們需要模板和靜態文件來聲稱更加豐富的網頁。模板即包含程序頁面的HTML文件,靜態文件是需要在HTML文件中加載的CSS和JS文件,以及圖片、字體文件等資源文件。默認情況下,模板文件存放在項目根目錄中的templates文件夾中,靜態文件存放在static文件夾下,這兩個文件需要和八平漢程序實例的模塊處于同意文件夾下,結構如下:
hello/
- templates
- static
- app.py