正如之前介紹的,F(xiàn)laskr 是一個(gè)數(shù)據(jù)庫(kù)驅(qū)動(dòng)的應(yīng)用,更準(zhǔn)確的說(shuō)法 是,一個(gè)由關(guān)系數(shù)據(jù)庫(kù)系統(tǒng)驅(qū)動(dòng)的應(yīng)用。關(guān)系數(shù)據(jù)庫(kù)系統(tǒng)需要一個(gè)模 式來(lái)決定存儲(chǔ)信息的方式。所以在第一次開(kāi)啟服務(wù)器之前,要點(diǎn)是創(chuàng) 建模式。

可以通過(guò)管道把 schema.sql 作為 sqlite3 命令的輸入來(lái)創(chuàng)建這 個(gè)模式,命令為如下:

sqlite3 /tmp/flaskr.db < schema.sql

這種方法的缺點(diǎn)是需要安裝 sqlite3 命令,而并不是每個(gè)系統(tǒng)都有安 裝。而且你必須提供數(shù)據(jù)庫(kù)的路徑,否則將報(bào)錯(cuò)。用函數(shù)來(lái)初始化數(shù)據(jù) 庫(kù)是個(gè)不錯(cuò)的想法。

要這么做,我們可以創(chuàng)建一個(gè)名為 init_db 的函數(shù)來(lái)初始化數(shù)據(jù)庫(kù)。 讓我們首先看看代碼。只需要把這個(gè)函數(shù)放在 flaskr.py 里的 connect_db 函數(shù)的后面:

def init_db():
    with app.app_context():
        db = get_db()
        with app.open_resource('schema.sql', mode='r') as f:
            db.cursor().executescript(f.read())
        db.commit()

那么,這段代碼會(huì)發(fā)生什么?還記得嗎?上個(gè)章節(jié)中提到,應(yīng)用環(huán)境在 每次請(qǐng)求傳入時(shí)創(chuàng)建。這里我們并沒(méi)有請(qǐng)求,所以我們需要手動(dòng)創(chuàng)建一 個(gè)應(yīng)用環(huán)境。 g 在應(yīng)用環(huán)境外無(wú)法獲知它屬于哪個(gè)應(yīng) 用,因?yàn)榭赡軙?huì)有多個(gè)應(yīng)用同時(shí)存在。

with app.app_context() 語(yǔ)句為我們建立了應(yīng)用環(huán)境。在 with 語(yǔ)句的內(nèi)部, g 對(duì)象會(huì)與 app 關(guān)聯(lián)。在語(yǔ)句的 結(jié)束處,會(huì)釋放這個(gè)關(guān)聯(lián)兵執(zhí)行所有銷(xiāo)毀函數(shù)。這意味著數(shù)據(jù)庫(kù)連接在 提交后斷開(kāi)。

應(yīng)用對(duì)象的 open_resource() 方法是一個(gè)很方便 的輔助函數(shù),可以打開(kāi)應(yīng)用提供的資源。這個(gè)函數(shù)從資源所在位置( 你的 flaskr 文件夾)打開(kāi)文件,并允許你讀取它。我們?cè)诖擞盟鼇?lái) 在數(shù)據(jù)庫(kù)連接上執(zhí)行腳本。

SQLite 的數(shù)據(jù)庫(kù)連接對(duì)象提供了一個(gè)游標(biāo)對(duì)象。游標(biāo)上有一個(gè)方法可 以執(zhí)行完整的腳本。最后我們只需提交變更。SQLite 3 和其它支持事 務(wù)的數(shù)據(jù)庫(kù)只會(huì)在你顯式提交的時(shí)候提交。

現(xiàn)在可以在 Python shell 導(dǎo)入并調(diào)用這個(gè)函數(shù)來(lái)創(chuàng)建數(shù)據(jù)庫(kù):

>>> from flaskr import init_db
>>> init_db()

故障排除

如果你遇到了表無(wú)法找到的異常,請(qǐng)檢查你是否確實(shí)調(diào)用過(guò) init_db 函數(shù)并且表的名稱(chēng)是正確的(比如弄混了單數(shù)和復(fù)數(shù))。

閱讀 Flask 視圖函數(shù) 以繼續(xù)。