04 Python Flask 教學10 所有文章

【Flask 教學】實作 Flask Blueprints 和淺談 Circular Imports

flask-blueprints-Max行銷誌

一. 從簡單的 Flask 開始

首先來看一個大家熟悉且單純的 Flask,運行 flask run 後,連線 http://127.0.0.1:5000/ 後,在網頁上會得到 foo 的字詞

app.py

from flask import Flask
import auth

app = Flask(__name__)

@app.route('/')
def index():
    return 'foo'

if __name__ == "__main__":
    app.run(debug=True)

1.當 Flask 架構越來越龐大…

但是隨著網站架構越來越龐大,把所有的 route 都放在 main.py 裡面,在維護上會有很大的困擾,所以我們開始試著把部分功能切到另外一個 py 檔案裡。

開始將 route 切出來,不再都集中在 app.py 內:

flask
├── app.py
└── userdata.py

app.py

from flask import Flask
import userdata

app = Flask(__name__)

@app.route('/')
def index():
    return 'foo'

if __name__ == "__main__":
    app.run(debug=True)

userdata.py

from app import app

@app.route('/auth')
def auths():
    return 'auth'

運行 flask

$ export FLASK_APP=app.py

$ flask run

連線 http://127.0.0.1:5000/auth 會發生 Not Found 的錯誤

The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.

會發生這個原因,是因為 import 循環衝突的問題造成,如下圖當運行 flask run 過後,會 import userdata 而在 userdata 裡面又會回來 import app,造成一個無限迴圈。

Flask Circular Imports 無限循環問題
Flask Circular Imports 無限循環問題

2.當遇上 Circular Imports 問題

一樣的資料夾結構

flask
├── app.py
└── auth.py

app.py

from flask import Flask
import auth

app = Flask(__name__)
auth.init_app(app)


@app.route('/')
def index():
    return 'foo'


if __name__ == "__main__":
    app.run(debug=True)

auth.py

def init_app(app):
    @app.route('/auth')
    def auths():
        return 'auth'

可以看到我們這次在 auth.py 裡面並沒有 from app import app,而是寫了一個涵式 def init_app(app)。當 app = Flask(__name__) 被準備好的時候,把 app 透過 auth.init_app(app) 的方式啟動 auth.py 裡面的路徑,這樣就可以避免無限循環的問題了!

Flask 運行

$ export FLASK_APP=app.py

$ flask run

連線 http://127.0.0.1:5000/auth 就會得到如預期的返回 auth 文字

二. 面對龐大架構,官方建議使用 Blueprints

Blueprints can greatly simplify how large applications work and provide a central means for Flask extensions to register operations on applications.

Modular Applications with Blueprints — Flask Documentation (1.1.x)

可使用 Flask Blueprints 將程式碼拆分成不同的模塊 (modules),Flask 並沒有強制規定切分的結構 (Architect),但常見的切分結構有以下兩者:

Flask 架構第一種:根據不同的功能建立專屬的 templates 和路徑。

ecommerce/
|
├── auth/
|   ├── templates/
|   |   └── auth/
|   |       ├── login.html
|   |       ├── forgot_password.html
|   |       └── signup.html
|   ├── __init__.py
|   └── auth.py
|
├── cart/
|   ├── templates/
|   |   └── cart/
|   |       ├── checkout.html
|   |       └── view.html
|   ├── __init__.py
|   └── cart.py
|
├── static/
|   ├── logo.png
|   ├── main.css
|   └── generic.js
|
├── app.py
├── config.py
└── models.py

Flask 架構第二種:僅使用 Flask Blueprints 切分路徑,但 templates 統一放在主資料夾下的 templates 內。

ecommerce/
|
├── static/
|   ├── logo.png
|   └── main.css
|
├── templates/
|   ├── auth/
|   |   ├── login.html
|   |   ├── forgot_password.html
|   |   └── signup.html
|   └── cart/
|       ├── checkout.html
|       └── view.html
|
├── view/
|   ├── auth.py
|   └── cart.py
|
├── app.py
├── config.py
└── models.py

兩種結構方法各適合不同的情境使用,提供給大家參考

開始實作 Flask Blueprints 教學

1.環境設置

*注意:Blueprints 不需要額外安裝套件,我們會從 from flask import Blueprint 中引入即可。

此次的資料夾結構

/flask
├── /view
│   └── api.py
└── main.py

此次需的 requirements 套件,僅安裝了 flask 1.1.2 的版本

click==7.1.2
Flask==1.1.2
itsdangerous==1.1.0
Jinja2==2.11.2
MarkupSafe==1.1.1
Werkzeug==1.0.1

2.開始建置 Flask Blueprints

1.設定 main.py 檔

首先使用 app.register_blueprint 註冊出新的 app,並且命名為 app2

檔案位置:flask/main.py

from flask import Flask, Blueprint
from view.api import app2

app = Flask(__name__)

@app.route('/')
def index():
        return "Hello index"

app.register_blueprint(app2)
2. 設定 api.py 檔

就可以使用剛剛在 main.py 註冊出新的 app2,並使用 @app2.route() 來創造出新路徑

檔案位置:flask/view/api.py

from flask import Blueprint

app2 = Blueprint('app2', __name__)

@app2.route('/app2')
def show(page):
        return "Hello Blueprint app2"
3. 運行 Flask
> export FLASK_APP=main.py
> flask run

並且連線 http://127.0.0.1:5000/app2 就可以連到剛剛切出來的 app2 囉!

4. Blueprints 進階參數設定

▍常用的參數設定: url_prefix

app.register_blueprint(app2, url_prefix='/pages')

代表未來所有的 app2 所創建出來的路徑,前面網址都需要加上 pages,所以如果我們今天要連上剛剛創建的 @app2.route('/app2'),網址是 http://127.0.0.1:5000/pages/app2

▍常用的參數設定: static_foldertemplate_folder

app2 = Blueprint('app2', __name__, static_folder='static')

可以指定新註冊的 app2 使用的 static 位置

app2 = Blueprint('app2', __name__, template_folder='templates')

可以指定新註冊的 app2 使用的 template 位置

本篇參考的相關文章:

更多 Flask 教學相關閱讀:

▍關於 Flask 教學系列目錄:

▍關於 Flask 部署相關文章:

▍其他 Flask 相關教學:

有關 Max行銷誌的最新文章,都會發佈在 Max 的 Facebook 粉絲專頁,如果想看最新更新,還請您按讚或是追蹤唷!

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *