Flask 藍圖(Blueprint)的引入及應用

咱們都知道 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。瀏覽器

404

而 127.0.0.1:5000/ 卻能正常響應!安全

200

這是爲何呢? 爲何在 view.py 中註冊的視圖函數找不到呢? 緣由就是由於循環導入,咱們在 run.py 中導入了 view, 同時又在 view.py 中導入了 run.py 中的 app!最終致使什麼結果呢,咱們經過調試來發現吧!app

詳解循環導入

  • 啓動 run, 第一次實例化一個 Flask 的核心對象 app,執行到導入 view 代碼,這是第一個關鍵點1!

  • 在 view.py 中,執行到導入 app 的代碼,轉而去執行 run.py 中的代碼

  • 能夠看到程序又再一次執行了 run.py 中的代碼,同時又一次實例化了一個 Flask 的核心對象,爲了區分,咱們將它稱爲 app2,這是第二個關鍵點 2 !

因爲,本次執行 __ name __ != __ main __,因此並不會執行 app.run()。那麼程序將繼續執行 view.py 中剩餘代碼框架

能夠看到,程序將相關的路由函數註冊到了 app2 上面! 當 view.py 中代碼執行完成以後,將繼續執行 run.py 中後面的代碼。也就是前面提到的關鍵點 1 以後的相關代碼!模塊化

此時將路由函數 index 註冊到了 app 上面,同時 __ name __ == __ main __,因此 app.run() 啓動成功!

經過上面的分析,總結以下:

  • 整個過程初始化了兩次 Flask 核心對象,app 和 app2
  • view 中的視圖函數註冊在 app2 上面
  • index 視圖函數註冊了兩次,第一次註冊到 app2,最後一次註冊 app 上面
  • 最終啓動的核心對象是 app

如今你應該明白了,view.py 中的視圖函數註冊的 app 和最終啓動的 app 不是同一個,因此最終致使找不到視圖函數!爲了能有個更直觀的感覺,咱們能夠將 app 的內存地址打印出來,這樣更加一目瞭然!

藍圖

解決方案:Flask 給咱們提供一種機制,藍圖(Blueprint)。 藍圖就是一個存儲操做路由映射方法的容器,主要用來實現客戶端請求和 URL 相互關聯的功能。 藍圖相似 Django 中的 app,二者的功能很是類似,幫助咱們實現模塊化應用的功能。

在 Flask 中能夠建立多個藍圖,表明不一樣的功能模塊。好比,上面代碼中的 web 文件夾就能做爲一個藍圖,另外用戶相關的功能模塊 user 也能建立一個相應的藍圖

解決問題

瞭解藍圖的相關功能以後,咱們正式經過藍圖來解決以上問題。

  • 首先在web/__ init __.py 文件中建立藍圖:
# coding: utf-8
__author__ = 'Jerry'
from flask import Blueprint

api = Blueprint('api', __name__)

from app.web import view

if __name__ == '__main__':
    pass
複製代碼
  • 藍圖建立完以後,在 view.py 中導入對應的藍圖,並將視圖函數註冊到藍圖中,改造完以後以下:
# 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}"
複製代碼
  • 咱們自始至終都要清楚,Flask 中的相關功能插件以及視圖函數最終都要註冊到核心對象上面,因此藍圖也是要註冊到核心對象上面。同時要了解到,當項目功能較多,用的插件也不少的時候,核心對象的初始化以及藍圖、第三方插件的註冊的相關代碼會不少,這時候也要對代碼進行分離。

因此在 app/__ init __.py 文件中作核心對象的初始化,同時將藍圖註冊到核心對象上。代碼以下:

同時在啓動文件 run.py 記得導入 app 核心對象,修改後代碼以下:

run.py

驗證結果

運行以後,咱們在瀏覽器中或者用代碼來驗證一下 GET 請求

POST 請求

完美!

相關文章
相關標籤/搜索