昨天講完了 manage.py
跟我們新加入的幾個自訂指令,今天我們還是離不開 manage.py
,而且昨天引入但是沒有用到的 db
也要登場了。
今天要登場的是 database migration,它是用來更新資料庫結構的,可以想成資料庫的版本控制。
我們要先在 manage.py
裡面加入以下幾行。
from flask_migrate import Migrate
migrate = Migrate(app, db, render_as_batch=True)
這樣就完成了,現在我們可以使用 flask
指令來處理資料庫的變化了。
在開始之前,我們要先把 data.db
(之前生出來的資料庫檔案) 刪掉,然後重新開始。
最一開始,我們需要先初始化,要使用 flask db init
,他應該會跑一下下,然後生出一個叫做 migration/
的目錄,但現在裡面還沒甚麼內容。
接著我們要使用 flask db migrate -m "description"
來建立一個版本,-m
後面要加上這個版本的說明之類的,有點像 git 的感覺。而這個版本的來源是我們的 models.py
,而不是現在資料庫的樣子。這樣一來,他就會生出一個新的版本,放在 migration/versions/
裡面,他會有一個獨特的編號,像 git 每一個 commit 都有編號一樣。
但建好這個版本之後,我們資料庫還沒有跟上,必須要使用 flask db upgrade
來把它升級到新版本,理論上第一個版本應該是建立好三個 table。這時候打開資料庫,應該會看到裡面已經有建好的 table,然後還有外加一個 Flask-Migrate 在用的 table。
我們現在可以嘗試在這個資料庫裡面加入一些資料,加入文章跟留言會被昨天提到的外鍵卡到,所以我們加入一個新的使用者來當作範例,看等等建立新版並且升級之後這筆資料會發生甚麼事。
接著我們到 models.py
稍微調整一下資料庫結構,我們嘗試加入一個 test = db.Column(db.String)
在 Users
裡面。現在我們的 models.py
已經更動了,所以我們可以建立新的版本,再次使用 flask db migrate
,這時候應該可以看到他會說偵測到有加入的 column,然後一個新版本就建好了。在升級之前我們可以看看一些小東西。flask db current
會讓你知道你現在在哪個版本,而 flask db heads
則會讓你知道現在的最新版本。
看完之後應該就可以看到 current
跟 heads
是不一樣的,所以這時候就可以再來 flask db upgrade
,讓他升級上去。最後我們打開資料庫,應該會看到 users
這個 table 已經更新了,加入了一個新的欄位,但同時舊的資料也沒有被刪除。
當然,這是一個測試用的版本,我們不會留在這個版本做事,所以我們要用 flask db downgrade
來退回前一個版本。在最一開始的初始化中,我們加入了一個 render_as_batch
的參數,會加入他是因為我們開發中先使用 sqlite,但他遇到刪除欄位的時候會爆炸,加上這個參數之後他就會換個方式,會變成把本來的資料庫砍掉然後重建,再把舊的資料複製過去新的,所以就可以避免掉 sqlite 不讓我們刪除的問題。
實作 Flask-Migrate更新資料庫
DAY26-搞懂Flask-Migrate
Flask實作 ext 06 Flask-Migrate
Why Flask-migrate cannot upgrade when drop column
Sqlite lack of ALTER support, Alembic migration failing because of this. Solutions?