前幾天有提到在工廠模式中,我們會用一個函式把全部 app
生起來,今天要實作的就是這個函式,一般習慣會使用 create_app
或 make_app
,我們選擇使用前者。
如同昨天所說,我們在 create_app
裡面會需要初始化一些東西,而這其中包括了資料庫。而我們會另外開一個 app/database
來處理資料庫的事務,初始化會用到的 db
也不例外,所以我們先來處理一下資料庫的相關作業。以下程式碼都會放在 app/database
中。
__init__.py
from .models import db
models.py
from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy()
很明顯地,app/database
也是一個 package。我們在 models.py
裡面宣告了 db
這個變數,也就是等等我們需要初始化 app
的幫手。接著在 __init__.py
裡面把 db
引入,這樣等等就可以讓別人引入。這個 models.py
是未來用來放資料庫結構的地方,但是我們還沒到那個部分,就先留著這樣就好。
接下來,我們就來看看該怎麼寫吧。我們要把這個函式放在 app/__init__.py
裡面。
from flask import Flask
from flask_login import LoginManager
from flask_mail import Mail
from flask_pagedown import PageDown
from flaskext.markdown import Markdown
from .database import db
from .config import configs
login_manager = LoginManager()
mail = Mail()
pagedown = PageDown()
def create_app(env):
app = Flask(__name__, template_folder="../templates", static_folder="../static")
app.config.from_object(configs[env])
login_manager.init_app(app)
db.init_app(app)
mail.init_app(app)
pagedown.init_app(app)
Markdown(app)
# Blueprint
from .main import main_bp
app.register_blueprint(main_bp)
from .user import user_bp
app.register_blueprint(user_bp)
from .admin import admin_bp
app.register_blueprint(admin_bp)
return app
一開始要先注意一下最後面 # Blueprint
後面的程式碼,他們目前都不存在,在未來我們會實做到。跟之前說過的一樣,基本上他們就是一堆路徑,然後分門別類放好,讓我們好管理。我們會用 register_blueprint
這個函式把整個藍圖加入 app
裡面。我們也可以使用 url_prefix
這個參數來設定這個藍圖的母路徑,例如說,我們設定 url_prefix="/auth"
,那在這個藍圖裡面的路徑前面都會被冠上 /auth
,如果他用的路徑是 /login
,那 register 過後就會變成 /auth/login
。但我們在此專案不會用到,所以先略過。
接著看到最上面的一堆引入,我們引入了 LoginManager
,他是 Flask-Login 的核心。也引入了 Mail
,他也是一個核心的概念,之後要寄信的時候就會直接找他。Pagedown
和 Markdown
也是相同的概念。再來是剛剛弄好的 db
,我們也需要他來初始化。最後還有之前寫好的設定檔對照表,讓我們可以根據環境來決定要用哪個設定。
接下來看到在下面我們把 LoginManager
、Mail
、Pagedown
和實體化,因為等等會用到這三個實體去初始化。
終於進入 create_app
函式本身了,當然我們需要先弄出 app
,但這次的宣告和之前的範例有些不同,多了 template_folder
和 static_folder
兩個參數,應該可以猜到,他們就是用來指定 jinja 模板目錄和 JS、CSS 那些檔案的目錄的,預設值分別是 templates
和 static
,如果不喜歡這個名字也可以自己改掉。這邊會需要設定是因為我們這兩個目錄跟 __init__.py
不是同一層目錄,需要往上一層。這個 create_app
接受了 env
這個參數,接下來我們就要用他來匯入之前寫的設定檔。flask 很好心地有一個函是可以讓我們直接從物件匯入,也就是此處的 app.config.from_object
,這樣一來,我們就可以抓到之前寫的設定檔了。
最後是初始化的部分,我們需要把五個東西都初始化,這樣才能在往後的開發中使用。要初始化的方法是使用他們的 init_app
函式,並以 app
作為參數。但 Markdown
比較特別,他沒有 init_app
這個函式,所以要像 db
那樣子做,而其他三個其實也可以不要先實體化變成 login_manager
,然後在 init_app
的位置初始化,像是 login_manager=LoginManager(app)
。但當然 db
沒有辦法這樣做,畢竟他在其他地方就定義好了。
Modular Applications with Blueprints