Python Flask學習知識點(二)

使用Flask寫簡單的API
所有API都一樣,不限於程式語言,API的難點在於路由(URL)的設計,能否精準的找到資源,而不是在於如何用技術實現。
在上一篇 ofollow,noindex">Python Flask學習知識點(一) 文章中,記錄瞭如何在試圖函式中返回資料。上篇文章說到Flask返回的本質是字串,通過content-type來控制返回的字串轉換為需要值,那麼我們在寫API的時候,API一般返回的都是JSON格式的資料,所以在檢視函式中要指定content-type為JSON。
@app.route() def search(): result = {"key1": "a", "key2": "b"} return json.dumps(result), 200, {"content-type": "application/json"}
解釋上圖程式碼片段:
我們一般通過檢視函式中做處理後拿到資料型別為python內建資料型別dict,而Flask要求,返回的結果必須是字串,所以我們用json.dumps(result)做處理後再返回。
後邊指定返回狀態碼200,和,返回的content-type為JSON。
以上就是一個簡單的API寫法。
jsonify()方法
Flask提供我們另外一個方法,便於簡化,jsonify().
改寫上部程式碼:
from flask import jsonify @app.route() def search(): result = {"key1": "a", "key2": "b"} return jsonify(result)
可以看到使用內建方法jsonify()要比原先的寫法更為簡潔。
將檢視函式拆分為單獨檔案
在某些業務場景下,業務功能很多,如果把所有的檢視函式全部放到單個檔案中,程式碼多不容易維護,其次就是從業務模型角度來講,不同的業務模型應該分配不同檔案當中,比如使用者模型和購物車模型,顯然不應該混合在同一檔案,業務模型應該分門別類。不推薦把所有檢視函式放到一個檔案中。
再一點就是,更加不應該將檢視函式放在啟動入口檔案當中,如下:
import json from flask import Flask app = Flask(__name__) # 把自定義的config.py配置檔案合併到flask配置檔案中 app.config.from_object("config") @app.route("/hello/") def hello(): return "hello" if __name__ == "__main__": app.run(host="0.0.0.0", debug=app.config['DEBUG'], port=81)
所以,重新建立專案目錄,原先專案目錄如下圖:

image.png
原先是一個配置檔案,一個入口啟動檔案,
現在新建一個名為app的資料夾,在app資料夾下新建一個名為web的資料夾,然後把檢視函式移到web資料夾下的book.py中,如圖:

image.png
book.py中的內容:
from flask import jsonify from run import app __author__ = 'Allen' @app.route('/hello') def search(): result = {"key1": "a"} return jsonify(result)
run.py中的內容:
from flask import Flask app = Flask(__name__) app.config.from_object('config') from app.web import book if __name__ == "__main__": app.run(host="0.0.0.0", debug=app.config['DEBUG'], port=81)
注意:由於在book.py中沒有app這個變數,所以從run.py中匯入app變數,看似沒有問題,實則問題很大!
會有什麼問題?
這時我們執行run.py啟動flask, 在瀏覽器中輸入127.0.0.1:81/hello會得到404錯誤,

image.png
404就是提示我們沒有找到/hello檢視函式。
深入瞭解flask路由
上邊看到,我們拆分完檢視函式後,執行報錯,
在Flask中,每一個URL對應一個檢視函式,中間還有一個叫做endpoint的東西,每一個URL有一個endpoint和一個檢視函式,如果通過URL正向尋找檢視函式時,endpoint顯得多餘,
但是通過檢視函式反向尋找URL函式時,endpoint是有用的。如下圖:

image.png
在上一篇 Python Flask學習知識點(一) 文章中,說明了Flask路由註冊的兩種方式,其中
app.add_url_rule("/hello/", view_func=hello)
這個add_url_rule方法中其實還有一個引數endpoint
app.add_url_rule("/hello/", view_func=hello, endpoint=)
因為Flask內部有判斷,如果我們不傳這個引數,Flask會做處理,把檢視函式的名字作為endpoint預設值傳入,具體檢視原始碼:

image.png
繼續看原始碼,url_map中添加了我們定義的路由規則rule, view_functions中把endpoint作為key,檢視函式作為value做儲存,下圖:

image.png
結論:如果路由要註冊成功,url_map物件中,rule(/hello)指向endpoint, view_functions字典中endpoint作為key,檢視函式作為value

image.png
一個成功的路由註冊,需要用endpoint作為橋樑來連線上URL和檢視函式。
迴圈引入
上邊提到,只有成功的註冊路由才可以訪問,但是已經成功的註冊後還是無法訪問,這個問題是因為這裡其實出現了 迴圈引用
。
在上邊run.py檔案中我們匯入了這樣一行程式碼:
from app.web import book
而在book.py中,我們匯入了這樣一行程式碼:
from run import app
以上兩行匯入程式碼會造成迴圈引用。
在執行run.py時程式碼執行到 from app.web import book
行時,會進入到book.py中,然後緊接著會執行到book.py中的這一行: from run import app
,然後又會進入到run.py中,大家可以斷點除錯下看效果。
此時,由於之前引用過一次from app.web import book,所以不會再引用,接著,因為run檔案中的app是被book.py匯入的,所以if name 不等於 "main",程式碼會回到book.py中繼續執行完,再跳回run.py中,成功啟動run.py。
建議大家反覆除錯理解。
在上邊過程中,其實app= Flask( name ) ,app物件初始化了兩次,我們用來註冊檢視函式的app和我們最終啟動的app是兩個不同的物件,由於迴圈匯入,導致出現兩個不同app物件。
驗證一下:
在run.py中列印app物件地址
from flask import Flask app = Flask(__name__) print(id(app)) app.config.from_object('config') from app.web import book if __name__ == "__main__": print(id(app)) app.run(host="0.0.0.0", debug=app.config['DEBUG'], port=81)
通過debug除錯,可以看到兩個記憶體地址不同,故為兩個不同的app物件。
欲知後事如何,請聽下回分解,記得點個贊~ 感謝。