起步
安裝
pip install alembic
# 初始化
alembic init alembic
配置
[alembic]
sqlalchemy.url = driver://user:pass@localhost/dbname
# 如下,修改為當(dāng)前使用的sql數(shù)據(jù)庫連接url
# sqlalchemy.url = postgresql://user:pass@localhost/dbname
- 修改配置alembic/env.py
- 搜索"target_metadata"找到代碼
- 如下是使用SQLModel
# 導(dǎo)入SQLModel,及自定義模型
from sqlmodel import SQLModel
from model.user import User
# target_metadata = None
target_metadata = SQLModel.metadata
遷移
- 創(chuàng)建遷移數(shù)據(jù)
- 通過對比數(shù)據(jù)庫表信息與所有遷移文件拐云,計算出差異字段后再生成新的遷移文件
- 首次使用甘耿,如果數(shù)據(jù)庫中已經(jīng)有表君躺,會影響首次遷移文件
- 建議先連接空數(shù)據(jù)庫第晰,生成遷移文件(記錄下alembic_version表的生成SQL谓苟,在數(shù)據(jù)庫中插入表)
- 將版本號加到"alembic_version"表中涕癣,就不會運(yùn)行重復(fù)執(zhí)行了
# 創(chuàng)建新記錄哗蜈,并添加表格遷移信息(--autogenerate)
alembic revision -m "add_xxx" --autogenerate
# 在alembic/versions目錄下生成一個遷移文件
# 升級
alembic upgrade head
# 創(chuàng)建almebic_version的表(如果不存在)
# 應(yīng)用遷移文件
# 僅打印sql文件,但暫不修改數(shù)據(jù)庫
alembic upgrade head --sql
# 降級
alembic downgrade <version>
# version在生成遷移文件里坠韩,找到down_revision字段
- 手動創(chuàng)建數(shù)據(jù)表如下
- 最好是連接空數(shù)據(jù)庫距潘,再記錄生成的SQL語句(需要引擎echo=True)
# 手動插入alembic數(shù)據(jù)表(Postgresql)
CREATE TABLE alembic_version (
version_num VARCHAR(32) NOT NULL,
CONSTRAINT alembic_version_pkc PRIMARY KEY (version_num)
);
# 插入版本號
INSERT INTO alembic_version (version_num) VALUES ('2fee77670444');
遷移
生成默認(rèn)值
- 想在已有數(shù)據(jù)的表中增加列,新增的列因為性能問題不為空只搁,需要設(shè)置個默認(rèn)值
from sqlmodel import SQLModel, Field, BigInteger, Integer, String
class User(SQLModel, table=True):
__tablename__ = "user"
id: int | None = Field(sa_type=BigInteger, default=None, primary_key=True)
name: str = Field(sa_type=String(32), default="")
# 新增年齡這一列
age: int = Field(sa_type=Integer, default=0, sa_column_kwargs={"comment": "年齡"})
- 修改生成的代碼音比,"age"字段中,增加"server_default"
* "default"字段在代碼端生效氢惋,比如插入記錄時洞翩,賦值默認(rèn)值
* "server_default"是設(shè)置數(shù)據(jù)庫端的默認(rèn)值稽犁,生成"... DEFAULT '0' ..."的SQL語句
* "server_default"只能是str/ClauseElement/TextClause(報錯會打印),將字符串設(shè)置為SQL語句中單引號內(nèi)得值即
# ...略
def upgrade() -> None:
op.add_column(
"user",
sa.Column(
"age",
sa.Integer(),
nullable=False,
comment="年齡",
server_default="0", # 手動添加該默認(rèn)值字段(使用default無效菱农,因為是代碼端生效)
),
)
# 或者直接寫SQL語句
op.execute("ALTER TABLE \"user\" ADD COLUMN age INTEGER DEFAULT '0' NOT NULL")
def downgrade() -> None:
op.drop_column("user", "age")
ALTER TABLE "user" ADD COLUMN age INTEGER DEFAULT '0' NOT NULL
配置
alembic.ini
[alembic]
# 文件命名格式缭付,默認(rèn)版本號是隨機(jī)的不方便查看,建議如下設(shè)置循未,文件格式"20241206-init-c28e8488d2bc.py"
file_template = %%(year)d%%(month).2d%%(day).2d-%%(slug)s-%%(rev)s
# 數(shù)據(jù)庫連接字符串陷猫,項目中不建議使用,而是在"alembic/env.py"切換到統(tǒng)一環(huán)境變量管理
sqlalchemy.url = driver://user:pass@localhost/dbname
alembic/env.py
# 初始值
# target_metadata = None
# 修改為
from sqlmodel import SQLModel # 或者導(dǎo)入sqlalchemy對應(yīng)的metadata
# 導(dǎo)入其他表對象的妖,如
# from models import User
target_metadata = SQLModel.metadata
# 該方法在"alembic upgrade head --sql"生效(有--sql參數(shù))
def run_migrations_offline() -> None:
# url = config.get_main_option("sqlalchemy.url")
# 數(shù)據(jù)庫連接從統(tǒng)一環(huán)境變量獲取
from setting import get_setting
url = get_setting().db_url
# 僅修改url來源绣檬,其他代碼不變
# 該方法在"alembic upgrade head"生效(無--sql參數(shù))
def run_migrations_online() -> None:
# connectable = engine_from_config(
# config.get_section(config.config_ini_section, {}),
# prefix="sqlalchemy.",
# poolclass=pool.NullPool,
# )
# 從自己項目導(dǎo)入數(shù)據(jù)庫引擎
from database import engine
connectable = engine
# 僅修改engine(其實也是改url來源),其他代碼不變
參考文檔