一、简介
Alembic是一个轻量的数据库迁移工具,使用 SQLAlchemy 作为底层引擎,为数据库提供变更管理脚本的创建、管理和调用。
二、安装
pip install alembic
三、使用
创建环境,生成一个迁移目录alembic:
cd /path/to/yourproject
alembic init alembic
可以使用list_templates 列出环境模板:
alembic list_templates
Available templates:
generic - Generic single-database configuration.
async - Generic single-database configuration with an async dbapi.
multidb - Rudimentary multi-database configuration.
pylons - Configuration that reads from a Pylons project environment.
创建环境的时候可以指定环境模板:
alembic init --template pylons ./scripts
迁移目录结构如下:
yourproject/
alembic/
env.py
README
script.py.mako
versions/
3512b954651e_add_account.py
2b1ae634e5cd_add_order_id.py
3adcc9a56557_rename_username_field.py
-
yourproject- 应用程序源代码的根目录 -
alembic- 迁移环境的主目录 -
env.py- 包含配置和生成 SQLAlchemy 引擎的指令,从该引擎获取连接以及事务,然后调用迁移引擎,使用连接作为数据库连接的来源 -
README- 信息文件 -
script.py.mako- 用于生成新的迁移脚本,用于在versions。可以控制每个迁移文件的结构,包括每个迁移文件中的标准导入,以及对upgrade()和downgrade()函数结构的更改。例如,multidb环境允许使用命名方案生成多个函数upgrade_engine1(),upgrade_engine2()。 -
versions/- 该目录包含各个版本的脚本
配置 .ini 文件:
alembic脚本在调用时查找的文件,基本格式如下:
[alembic]
# 迁移脚本路径
script_location = alembic
# 用于生成新迁移文件的模板
# file_template = %%(rev)s_%%(slug)s
# 添加路径到sys.path 路径之前
prepend_sys_path = .
# 时区名称
# timezone =
# slug 字符最大长度
# truncate_slug_length = 40
# 设置为true时,执行revision命令时,无视自动生成
# revision_environment = false
# 设置true时允许.pyc和.pyo文件作为版本控制,允许无源版本文件夹,
# 当保留默认值 'false' 时,只有 .py 文件被用作版本文件。
# sourceless = false
# 修订文件位置列表,允许修订同时存在于多个目录中
# version_locations = %(here)s/bar:%(here)s/bat:${script_location}/versions
# version path separator; As mentioned above, this is the character used to split
# version_locations. Valid values are:
#
# version_path_separator = :
# version_path_separator = ;
# version_path_separator = space
version_path_separator = os # default: use os.pathsep
# the output encoding used when revision files
# are written from script.py.mako
# output_encoding = utf-8
# 通过 SQLAlchemy 连接到数据库的 URL
sqlalchemy.url = driver://user:pass@localhost/dbname
# 日志配置
[loggers]
keys = root,sqlalchemy,alembic
[handlers]
keys = console
[formatters]
keys = generic
[logger_root]
level = WARN
handlers = console
qualname =
[logger_sqlalchemy]
level = WARN
handlers =
qualname = sqlalchemy.engine
[logger_alembic]
level = INFO
handlers =
qualname = alembic
[handler_console]
class = StreamHandler
args = (sys.stderr,)
level = NOTSET
formatter = generic
[formatter_generic]
format = %(levelname)-5.5s [%(name)s] %(message)s
datefmt = %H:%M:%S
[loggers],[handlers],[formatters],[logger_*],[handler_*],[formatter_*]- 这些部分都是 Python 标准日志记录配置的一部分。
创建迁移脚本:
环境就绪后,我们可以使用 alembic revision 命令创建新迁移脚本:
$ alembic revision -m "create account table"
Generating /path/to/yourproject/alembic/versions/1975ea83b712_create_accoun
t_table.py...done
将会在versions目录下生成一个新文件1975ea83b712_create_account_table.py:
"""create account table
Revision ID: 1975ea83b712
Revises:
Create Date: 2011-11-08 11:40:27.089406
"""
# revision identifiers, used by Alembic.
revision = '1975ea83b712'
down_revision = None
branch_labels = None
from alembic import op
import sqlalchemy as sa
def upgrade():
pass
def downgrade():
pass
需要注意的是down_revision变量,None代表第一个文件,当我们创建下一个修订版时,新文件的down_revision标识符将指向上一次的 revision 。
然后我们可以向我们的脚本添加一些指令,假设添加一个新表account:
def upgrade():
op.create_table(
'account',
sa.Column('id', sa.Integer, primary_key=True),
sa.Column('name', sa.String(50), nullable=False),
sa.Column('description', sa.Unicode(200)),
)
def downgrade():
op.drop_table('account')
执行迁移:
alembic upgrade head
head 代表最新的版本,如果我们想要迁移到指定版本,只需指定部分版本号:
alembic upgrade ae1
ae1用来指代修订版ae1027a6acf。
还支持相对升级/降级。要从当前移动两个版本,可以提供十进制值“+N”:
alembic upgrade +2
降级接受负值:
alembic downgrade -1
相对标识符也可以是特定版本。例如,升级到修订版ae1027a6acf加上两个额外的步骤:
alembic upgrade ae10+2
四、自动生成迁移
如果我们不想每次都自己手动修改迁移脚本,可以使用自动生成迁移脚本功能。
首先修改 env.py:
target_metadata = None
改为:
from myapp.mymodel import Base
target_metadata = Base.metadata
如果程序具有多个 Model :
from myapp.mymodel1 import Model1Base
from myapp.mymodel2 import Model2Base
target_metadata = [Model1Base.metadata, Model2Base.metadata]
MetaData在自动生成过程中将按顺序查询集合序列。
创建迁移文件:
alembic revision --autogenerate -m "Added account table"