前言
在 Flask application 中,我們通常會使用 Flask-SQLAlchemy (或 SQLAlchemy) 套件來操作資料庫,但它們只會在 table 不存在時才會建立新的 table, 若是之後 table 欄位有變動就需要整個 table 刪掉重建或是直接使用 SQL command 去更新 table schema,但是這兩種方式都不適合用於正式 production 的服務,而且若是直接使用 SQL command 去更新 table schema 會無法控管資料庫變更的紀錄,因此我們就需要 Flask-Migrate
這個套件來做資料庫的版控,這一篇文章就來紀錄一下使用方式。
Flask-Migrate
Flask-Migrate 是基於 alembic 再去做擴展的,能夠讓開發者更方便的整合 Flask 和 Flask-SQLAlchemy.
NOTE: 這一篇文章是以 Flask application 為主,若是使用其他框架 (Django, FastAPI) 也有相對應的 migration 方式,請參考 Django Migration 和 FastAPI SQL Database Migration.
Installation
1 | $ pip install flask-migrate |
Usage
假設目錄架構如下: (Application factories)
1 | flask-migration-example/ |
In app/extensions.py
:
1 | from flask_sqlalchemy import SQLAlchemy |
In app/models.py
:
1 | from .extensions import db |
In app/__init__.py
:
1 | from flask import Flask |
In wsgi.py
:
1 | from app import create_app |
設定好 Flask application 後,接著執行 init 指令:
1 | $ flask db init |
執行後會看到專案目錄底下會出現 migrations
資料夾:
接著執行以下指令來產生 migration scripts:
1 | # -m: Migration message |
最後執行 upgrade 指令將 migration script apply to database:
1 | $ flask db upgrade |
之後若是有更動,只要再執行 migrate
和 upgrade
指令即可~
若是需要降回以前版本,可以使用以下指令:
1 | $ flask db downgrade <revision> |
其他更多指令可使用 flask db --help
查看。
在現有專案中加入 Flask-Migrate
如果是要在現有專案且資料庫已存在的情況下,想要產生 initial migration,依照上述步驟執行之後會出現以下訊息:
1 | INFO [alembic.runtime.migration] Context impl MySQLImpl. |
因為現有的資料庫對 Flask-Migrate 來說是沒有變動的,可以再依照以下步驟來產生 initial migration:
一樣先 initialize, 建立 migrations
資料夾:
1 | $ flask db init |
接著需要讓 Flask-Migrate 認為資料庫是空的,有兩種方式:
- 將現有的資料庫重新命名,並再建立一個一樣名稱的空資料庫
- 建立一個新的空資料庫,暫時讓 application 使用該資料庫
再來執行 migrate
指令:
1 | $ flask db migrate |
這樣就可以 initial migration, 接著就可以將資料庫回復到原本正確的狀態或使用回原本的資料庫,並把現有資料庫標記為 updated:
1 | $ flask db stamp head |
之後若是有更新 table schema, 一樣再使用 migrate
和 upgrade
指令即可。
NOTE:
- 記得要將
migrations
加入 Git 版控 - 記得將所有環境(dev, test, production)的資料庫標記為 updated (
flask db stamp head
),之後就可以依照正常步驟來做 migration