python flask 使用 Blueprint 配合 current_app 發生錯誤 RuntimeError: Working outside of application context.?

 




在 Flask 中,當你在 Blueprint 中使用 current_app 時,必須確保 Flask 應用程式的 應用上下文 (application context) 是活動狀態的,否則會遇到 "RuntimeError: Working outside of application context" 錯誤。

錯誤原因
current_app 依賴於 Flask 的 應用上下文,但 Blueprint 是獨立於應用程式的。當你嘗試在 Blueprint 外部(例如模組級別)直接使用 current_app,或是在沒有開啟應用上下文的情況下使用它,就會導致錯誤。

解決方案
1. 使用 with app.app_context() 確保有應用上下文
在非請求處理(如初始化時)使用 app.app_context() 來確保 current_app 可以正常運作。

from flask import Flask, Blueprint, current_app

bp = Blueprint("example", __name__)

@bp.route("/")
def index():
    return f"App name: {current_app.name}"  # 這裡可以使用 current_app,因為請求處理期間 Flask 會自動提供應用上下文

def print_app_name():
    with current_app.app_context():  # 確保應用上下文有效
        print(current_app.name)

app = Flask(__name__)
app.register_blueprint(bp)

with app.app_context():  # 在 Blueprint 外部使用 current_app 需要手動開啟應用上下文
    print(current_app.name)


2. 使用 flask.current_app 只在請求期間存取
如果 current_app 是在請求處理函式內使用的,那麼不需要手動處理應用上下文,因為 Flask 會自動提供它。

@bp.route("/config")
def get_config():
    return current_app.config["DEBUG"]  # 這裡可以安全地使用 current_app


3. 在 Blueprint 模組內避免全域變數存取 current_app
如果 current_app 是在 Blueprint 外部(模組級別)使用的,應該改用 Flask 應用程式的 app.config,或者使用函數來動態存取 current_app。

錯誤範例(不應該在 Blueprint 頂部存取 current_app)

from flask import current_app

# X 這會導致錯誤,因為 current_app 只能在應用上下文中存取
db_uri = current_app.config["SQLALCHEMY_DATABASE_URI"]


正確作法

def get_db_uri():
    return current_app.config["SQLALCHEMY_DATABASE_URI"]

@bp.route("/db")
def show_db_uri():
    return get_db_uri()


4. 改用 app.config 來存取設定
如果你需要在 Blueprint 外部的模組級別存取設定,建議直接從 Flask 應用程式的 app.config 來取得。

def create_app():
    app = Flask(__name__)
    app.config["MY_SETTING"] = "Hello, Flask!"
    app.register_blueprint(bp)
    return app

def some_function():
    from flask import current_app
    with current_app.app_context():
        print(current_app.config["MY_SETTING"])


結論


current_app 只能在 Flask 應用上下文內 存取。
解決方法
在非請求處理代碼中,使用 with app.app_context() 來開啟應用上下文。
只在請求期間使用 current_app,因為 Flask 會自動提供應用上下文。
避免在 Blueprint 模組級別存取 current_app,應該改用函數來動態取得設定值。
在應用初始化時,建議直接使用 app.config 來存取設定。
這樣可以避免 "RuntimeError: Working outside of application context" 錯誤。