咱們都知道 flask 是一個輕量級的 web 框架,相對於其餘同類型框架更爲靈活、輕便、安全且容易上手。開發者能夠隨意編寫本身想要的項目結構,同時還有不少的第三方庫供君選擇。可是靈活的同時也帶來了相應的問題,好比對不少初學者來講,建的項目結構混亂,不易維護,還有經典的循環導入等問題python
不少初學者喜歡將啓動文件和多個路由寫在同一個文件中,例如如下代碼:web
這樣一旦隨着視圖函數的增多,代碼的可維護性會變得愈來愈差。因此有必要對視圖函數進行拆分。 咱們將其拆分紅兩個文件: run.py 和 view.py,其中 run.py 做爲程序的啓動文件,由於要將路由註冊到 flask 核心對象上,因此在 view.py 中須要導入核心對象,同時 run.py 中要導入 view 最終,代碼和項目結構以下所示:json
run.pyflask
# coding: utf-8
__author__ = 'Jerry'
from flask import Flask
app = Flask(__name__)
from app.web import view
@app.route("/")
def index():
return 'Hello World'
if __name__ == '__main__':
app.run()
複製代碼
view.pyapi
# coding: utf-8
__author__ = 'Jerry'
from flask import request
from run import app
@app.route("/add")
def add():
name = request.args.get("name")
return f"Add {name}"
@app.route("/delete")
def delete():
name = request.args.get("name")
return f"Delete {name}"
@app.route("/change",methods=["POST"])
def change():
num = request.json
return f"change {num}"
複製代碼
可是當我啓動程序,在瀏覽器中輸入地址 http://127.0.0.1:5000/add?name=Jerry 以後,報 404 Not Found。瀏覽器
而 127.0.0.1:5000/ 卻能正常響應!安全
這是爲何呢? 爲何在 view.py 中註冊的視圖函數找不到呢? 緣由就是由於循環導入,咱們在 run.py 中導入了 view, 同時又在 view.py 中導入了 run.py 中的 app!最終致使什麼結果呢,咱們經過調試來發現吧!app
因爲,本次執行 __ name __ != __ main __,因此並不會執行 app.run()。那麼程序將繼續執行 view.py 中剩餘代碼框架
能夠看到,程序將相關的路由函數註冊到了 app2 上面! 當 view.py 中代碼執行完成以後,將繼續執行 run.py 中後面的代碼。也就是前面提到的關鍵點 1 以後的相關代碼!模塊化
此時將路由函數 index 註冊到了 app 上面,同時 __ name __ == __ main __,因此 app.run() 啓動成功!
經過上面的分析,總結以下:
如今你應該明白了,view.py 中的視圖函數註冊的 app 和最終啓動的 app 不是同一個,因此最終致使找不到視圖函數!爲了能有個更直觀的感覺,咱們能夠將 app 的內存地址打印出來,這樣更加一目瞭然!
解決方案:Flask 給咱們提供一種機制,藍圖(Blueprint)。 藍圖就是一個存儲操做路由映射方法的容器,主要用來實現客戶端請求和 URL 相互關聯的功能。 藍圖相似 Django 中的 app,二者的功能很是類似,幫助咱們實現模塊化應用的功能。
在 Flask 中能夠建立多個藍圖,表明不一樣的功能模塊。好比,上面代碼中的 web 文件夾就能做爲一個藍圖,另外用戶相關的功能模塊 user 也能建立一個相應的藍圖
瞭解藍圖的相關功能以後,咱們正式經過藍圖來解決以上問題。
# coding: utf-8
__author__ = 'Jerry'
from flask import Blueprint
api = Blueprint('api', __name__)
from app.web import view
if __name__ == '__main__':
pass
複製代碼
# coding: utf-8
__author__ = 'Jerry'
from flask import request
from . import api
print(f"註冊view中的app: {id(api)}")
@api.route("/add")
def add():
name = request.args.get("name")
return f"Add {name}"
@api.route("/delete")
def delete():
name = request.args.get("name")
return f"Delete {name}"
@api.route("/change", methods=["POST"])
def change():
num = request.json
return f"change {num}"
複製代碼
因此在 app/__ init __.py 文件中作核心對象的初始化,同時將藍圖註冊到核心對象上。代碼以下:
同時在啓動文件 run.py 記得導入 app 核心對象,修改後代碼以下:
運行以後,咱們在瀏覽器中或者用代碼來驗證一下 GET 請求
POST 請求
完美!