WeHelp
淺談 Flask Blueprint 使專案更加方便管理和維護
2022-12-01 21:27:45
# 淺談 Flask Blueprint 使專案更加方便管理和維護 ## 什麼是 Blueprint 能幫助我們做什麼? * Factor an application into a set of blueprints. This is ideal for larger applications; a project could instantiate an application object, initialize several extensions, and register a collection of blueprints. * Register a blueprint on an application at a URL prefix and/or subdomain. Parameters in the URL prefix/subdomain become common view arguments (with defaults) across all view functions in the blueprint. * Register a blueprint multiple times on an application with different URL rules. * Provide template filters, static files, templates, and other utilities through blueprints. A blueprint does not have to implement applications or view functions. * Register a blueprint on an application for any of these cases when initializing a Flask extension. 簡單來說,當專案隨著架構越來越龐大,如果把程式都寫在同一個主程式裡面,會造成管理非常困難 ,所以使用 **Flask Blueprint** 可以把每一個項目分離出來,要修改和維護就方便許多。 舉例在自製的圖書館專案中,把每個網頁和 api 的 route 集中在 app.py,看起來非常雜亂,不好管理。 ``` myapp ├─ static ├─ templates └─ app.py ``` ```python from flask import Flask, render_template app = Flask(__name__) # 首頁 @app.route("/") def index(): return render_template("index.html") # 會員 @app.route("/member") def signig(): return render_template("member.html") # 書本api @app.route("/api/book") def api_book(): return {"key" : "book"} # 作者api @app.route("/api/authors") def api_authors(): return {"key" : "author"} # 書本頁面 @app.route("/book") def list(): return render_template("book.html") # 尋找書本頁面 @app.route("/book/<int:id>") def getItem(id:int): return render_template("content.html",id=id) # 作者首頁 @app.route("/authors") def authors_list(): return render_template("authors.html") # 尋找作者頁面 @app.route("/authors/<int:id>") def authors_getItem(id:int): return render_template("detail.html",id=id) app.run(host="127.0.0.1",port=3050,debug=True) ``` ## 使用 Blueprint 看起來會怎樣? 舉例先把 api 跟 app.py 分開來,這樣修改內容起來就方便許多。 ``` myapp ├─ api/ | ├─ books_api.py | └─ authors_api.py ├─ static ├─ templates └─ app.py ``` ## 第一步 : 創建 Flask Blueprint ### 首先先匯入 Blueprint 套件 ```python from flask import Blueprint ``` ### 定義創建的 Blueprint 名字 ```python select_books = Blueprint("select_books",__name__) ``` ### 使用的定義 Blueprint 的 route ```python @select_books.route("/api/book") def api_book(): return {"key" : "book"} ``` ```python from flask import Blueprint select_books = Blueprint("select_books",__name__) # 書本api @select_books.route("/api/book") def api_book(): return {"key" : "book"} ``` ### 註冊 Flask Blueprint ```python from api.books_api import select_books app.register_blueprint(select_books) ``` 相同的做法分開另一個 **api** 後,之後管理和維護相關 **api** 程式就簡單許多了。 ```python from flask import Flask, render_template from api.authors_api import select_authors from api.books_api import select_books app = Flask(__name__) # 首頁 @app.route("/") def index(): return render_template("index.html") # 會員 @app.route("/member") def signig(): return render_template("member.html") # 書本頁面 @app.route("/book") def list(): return render_template("book.html") # 尋找書本頁面 @app.route("/book/<int:id>") def getItem(id:int): return render_template("content.html",id=id) # 作者首頁 @app.route("/authors") def authors_list(): return render_template("authors.html") # 尋找作者頁面 @app.route("/authors/<int:id>") def authors_getItem(id:int): return render_template("detail.html",id=id) app.register_blueprint(select_authors) app.register_blueprint(select_books) app.run(host="127.0.0.1",port=3050,debug=True) ``` ## Blueprint 設定參數說明 ```python from flask import Blueprint example_blueprint = Blueprint('example_blueprint', __name__) ``` 仔細說明 **Blueprint** 參數說明,第一個參數是說明 **Blueprint** 的名稱,第二個參數 **&#95;&#95;name&#95;&#95;** 是導入 **Blueprint** 的名稱,**Flask** 使用它來定位 **Blueprint**。 Blueprint 提供其他可選參數設定路徑 * **static_folder:** the folder where the Blueprint’s static files can be found * **static_url_path:** the URL to serve static files from * **template_folder:** the folder containing the Blueprint’s templates * **url_prefix:** the path to prepend to all of the Blueprint’s URLs * **subdomain:** the subdomain that this Blueprint’s routes will match on by default * **url_defaults:** a dictionary of default values that this Blueprint’s views will receive * **root_path:** the Blueprint’s root directory path, whose default value is obtained from the Blueprint’s import name ```python app.register_blueprint(simple_page, url_prefix='/pages') ``` ```python simple_page= Blueprint('simple_page', __name__, url_prefix='/parent') ``` ## 進階 Blueprint 設定 這邊介紹 **url_prefix** 的使用方法,分離 **authors** 和 **books** 的網頁 **route**。 ``` myapp ├─ api/ | ├─ books_api.py | └─ authors_api.py ├─ controllers/ | ├─ authors.py | └─ books.py ├─ static ├─ templates/ | ├─ authors/ | | ├─ authors.html | | └─ detail.html | ├─ books/ | | ├─ book.html | | └─ content.html | ├─ index.html | └─ member.html └─ app.py ``` ```python from flask import Blueprint,render_template authors_ctrlr = Blueprint("authors", __name__) # 作者首頁 @authors_ctrlr.route("/") def authors_list(): return render_template("authors/authors.html") # 尋找作者頁面 @authors_ctrlr.route("/<int:id>") def authors_getItem(id:int): return render_template("authors/detail.html",id=id) ``` 在 **templates** 裡建立了兩個資料夾 **authors** 和 **books** ,所以這邊 **render_template** 位置選擇相對的地方,在 **route** 的部分會在 **app.py** 會利用 **url_prefix** 裡設定網址路徑。 ### 註冊和引入 Blueprint ```python from controllers.books import books_ctrlr from controllers.authors import authors_ctrlr app.register_blueprint(authors_ctrlr, url_prefix="/authors") app.register_blueprint(books_ctrlr, url_prefix="/books") ``` 這邊 **url_prefix** 分別設定 **/authors** 和 **/books** , 所以相對的在網址填入就會分別引導到 **authors** 和 **books** 的 **html route** 上面。 **app.py** 就分離了 **authors** 和 **books** 的網頁。 ```python from flask import Flask, render_template from api.authors_api import select_authors from api.books_api import select_books from controllers.books import books_ctrlr from controllers.authors import authors_ctrlr app = Flask(__name__) # 首頁 @app.route("/") def index(): return render_template("index.html") # 會員 @app.route("/member") def signig(): return render_template("member.html") app.register_blueprint(authors_ctrlr, url_prefix="/authors") app.register_blueprint(books_ctrlr, url_prefix="/books") app.register_blueprint(select_authors) app.register_blueprint(select_books) app.run(host="127.0.0.1",port=3050,debug=True) ``` ### 執行程式 **首頁** ![image](wehelp-storage://b603bb5cb911d893c7814785ac21c0b1) **book api** ![image](wehelp-storage://1815cd122d8056ca4a6ddcaf4bd7b61e) **author api** ![image](wehelp-storage://d9e11fe2c5142d836f2220488b9d5957) **book 網頁** ![image](wehelp-storage://398f6bd2bc353d39793cf883bcd94c88) ![image](wehelp-storage://589ac619db67eb1677314e89afb0e9e2) **author 網頁** ![image](wehelp-storage://5528ecf69908db473a63fd0dd8da4888) ![image](wehelp-storage://7a666bfbf8b7b18919b56c7d58a8fdd7) 最後關於參數設定路徑的方法還有很多種,以下網址有提供相關的做法。 參考連結: [https://flask.palletsprojects.com/en/2.2.x/blueprints/](https://flask.palletsprojects.com/en/2.2.x/blueprints/) [https://realpython.com/flask-blueprint/](https://realpython.com/flask-blueprint/) [https://www.freecodecamp.org/news/how-to-use-blueprints-to-organize-flask-apps/](https://www.freecodecamp.org/news/how-to-use-blueprints-to-organize-flask-apps/) [https://medium.com/seaniap/python-web-flask-blueprints-解決大架構的網站-1f9878312526](https://medium.com/seaniap/python-web-flask-blueprints-%E8%A7%A3%E6%B1%BA%E5%A4%A7%E6%9E%B6%E6%A7%8B%E7%9A%84%E7%B6%B2%E7%AB%99-1f9878312526) https://www.youtube.com/watch?v=SezbDCz0Ock&t=912s