Table
一. 從簡單的 Flask 開始
首先來看一個大家熟悉且單純的 Flask,運行 flask run
後,連線 http://127.0.0.1:5000/ 後,在網頁上會得到 foo 的字詞
app.py
1 2 3 4 5 6 7 8 9 10 11 |
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 內:
1 2 3 |
flask ├── app.py └── userdata.py |
app.py
1 2 3 4 5 6 7 8 9 10 11 |
from flask import Flask import userdata app = Flask(__name__) @app.route('/') def index(): return 'foo' if __name__ == "__main__": app.run(debug=True) |
userdata.py
1 2 3 4 5 |
from app import app @app.route('/auth') def auths(): return 'auth' |
運行 flask
1 2 3 |
$ export FLASK_APP=app.py $ flask run |
連線 http://127.0.0.1:5000/auth 會發生 Not Found 的錯誤
1 |
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,造成一個無限迴圈。

2.當遇上 Circular Imports 問題
一樣的資料夾結構
1 2 3 |
flask ├── app.py └── auth.py |
app.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
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
1 2 3 4 |
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 運行
1 2 3 |
$ 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 和路徑。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
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 內。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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
中引入即可。
此次的資料夾結構
1 2 3 4 |
/flask ├── /view │ └── api.py └── main.py |
此次需的 requirements 套件,僅安裝了 flask 1.1.2 的版本
1 2 3 4 5 6 |
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
1 2 3 4 5 6 7 8 9 10 |
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
1 2 3 4 5 6 7 |
from flask import Blueprint app2 = Blueprint('app2', __name__) @app2.route('/app2') def show(page): return "Hello Blueprint app2" |
3. 運行 Flask
1 2 |
> export FLASK_APP=main.py > flask run |
並且連線 http://127.0.0.1:5000/app2 就可以連到剛剛切出來的 app2 囉!
4. Blueprints 進階參數設定
▍常用的參數設定: url_prefix
1 |
app.register_blueprint(app2, url_prefix='/pages') |
代表未來所有的 app2 所創建出來的路徑,前面網址都需要加上 pages,所以如果我們今天要連上剛剛創建的 @app2.route('/app2')
,網址是 http://127.0.0.1:5000/pages/app2
▍常用的參數設定: static_folder
、template_folder
1 |
app2 = Blueprint('app2', __name__, static_folder='static') |
可以指定新註冊的 app2 使用的 static 位置
1 |
app2 = Blueprint('app2', __name__, template_folder='templates') |
可以指定新註冊的 app2 使用的 template 位置
本篇參考的相關文章:
- Modular Applications with Blueprints — Flask Documentation (1.1.x)
- Flask Factory Pattern to set up your project. | by Felipe Florencio Garcia | ITNEXT
- Flask Blueprints — Complete Tutorial to fully understand how to use it! | by Felipe Florencio Garcia | Jun, 2020 | ITNEXT
- Use a Flask Blueprint to Architect Your Applications – Real Python
更多 Flask 教學相關閱讀:
▍關於 Flask 教學系列目錄:
▍關於 Flask 部署相關文章:
- 【Flask 教學系列】實作 GCP 部署 Flask + Nginx + uWSGI
- 第一集:實作 Dockerfile + flask 教學 (附GitHub完整程式)
- 第二集:實作 Dockerfile + nginx + ssl + flask 教學 (附GitHub完整程式)
- 第三集:實作 Docker-compose (Flask+Nginx+PostgreSQL)
- 【Flask 教學系列】實作 Flask + GitHub Action CI/CD
▍其他 Flask 相關教學:
- 【Flask教學系列】Flask 為甚麼需要 WSGI 與 Nginx
- 【Flask教學系列】Flask-SQLAlchemy 資料庫連線&設定入門 (一)
- 【Flask教學系列】Flask-JWT-Extended 實作
- 【Flask教學系列】實作 Flask CORS
- 【Flask教學系列】實作 Flask CSRF Protection
有關 Max行銷誌的最新文章,都會發佈在 Max 的 Facebook 粉絲專頁,如果想看最新更新,還請您按讚或是追蹤唷!
在〈【Flask 教學】實作 Flask Blueprints 和淺談 Circular Imports〉中有 2 則留言
當遇上 Circular Imports 問題那段,我想請問雖然沒有報錯了,但是只有輸出foo,沒有輸出auth,請問這樣是正確的嗎?
不好意思,已經解決了,我忘了http://127.0.0.1:5000/auth在最後面加上/auth,謝謝。
留言功能已關閉。