背景:
在开发时,以删除表再重建的方式更新数据库简单直接,但明显的缺陷是会丢掉数据库中的所有数据。在生产环境下,你绝对不会想让数据库里的数据都被删除掉,这时你需要使用数据库迁移工具来完成这个工作。SQLAlchemy的开发者MichaelBayer写了一个数据库迁移工具-Alembic来帮助我们实现数据库的迁移,数据库迁移工具可以在不破坏数据的情况下更新数据库表的结构。蒸馏器(Alembic)是炼金术士最重要的工具,要学习SQL炼金术( SQLAlchemy),我们当然要掌握蒸馏器的使用。
1.安装flask-migrate
扩展Flask-Migrate集成了Alembic,提供了一些flask命令来简化迁移工作,我们将使用它来迁移数据库。Flask-Migrate及其依赖(主要是Alembic)可以使用Pipenv安装:
$ pipenv install flask-migrate
2.在程序中实例化Migrate类
实例化Migrate类时,除了传入程序实例app,还需要传入实例化Flask-SQLAlchemy提供的SQLAlchemy类创建的db对象作为第二个参数。
from flask import Flask
from flask sqlalchemy import SQLAlchemy
from flask_migrate import Migrate
app = Flask( name )
# ....增加一下配置信息,这里就不写了
db= SQLAlchemy(app)
# 实例化Migrate类
migrate= Migrate(app, db)
3. 创建迁移环境
在开始迁移数据之前,需要先使用下面的命令创建一个迁移环境:
$ flask db init
附注:Flask-Migrate提供了一个命令集,使用db作为命名集名称,它提供的命令都以
flask db
开头。你可以在命令行中输入flask --help
查看所有可用的命令和说明。
迁移环境只需要创建一次。这会在你的项目根目录下创建一个migrations文件夹,其中包含了自动生成的配置文件和迁移版本文件夹。
4.生成迁移脚本
使用migrate子命令可以自动生成迁移脚本:
$ flask db migrate -m "add article create_time”
INFO [alembic.autogenerate.compare] Detected added column 'article.create_time'
Generating D:\test\migrations\versions\bbfe25d9b3c0_.py ... done
这条命令可以简单理解为在flask里对数据库(db)进行迁移(migrate)。-m选项用来添加迁移备注信息。从上面的输出信息我们可以看到,Alembic检测出了模型的变化:表article 新添加了一个create_time列,并且相应生成了一个迁移脚本bbfe25d9b3c0_add_article_create_time.py, 脚本的内容如下所示:
from alembic import op
import sqlalchemy as sa
# .......
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.add_column('article', sa.Column('create_time', sa.DateTime(), nullable=True))
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column('article', 'create_time')
# ### end Alembic commands ###
从上面的代码可以看出,迁移脚本主要包含了两个函数:upgrade()函数用来将改动应用到数据库,函数中包含了向表中添加create_time字段的命令;而downgrade()函数用来撤销改动,包含了删除create_time字段的命令。
注意:就像这两个函数中的注释所说的,迁移命令是由Alembic自动生成的,其中可能包含错误,所以有必要在生成后检查一下。
因为每一次迁移都会生成新的迁移脚本,而且Alembic为每一次迁移都生成了修订版本( revision) ID,所以数据库可以恢复到修改历史中的任一点。正因为如此,迁移环境中的文件也要纳入版本控制。
有些复杂的操作无法实现自动迁移,这时可以使用revision命令手动创建迁移脚本。这同样会生成一个迁移脚本,不过脚本中的upgrade()和downgrade()函数都是空的。
你需要使用Alembic提供的Operations对象指令在这两个函数中实现具体操作,具体可以访问Alembic官方文档查看。
3.更新数据库
生成了迁移脚本后,使用upgrade子命令即可更新数据库:
# 上面只是生成了迁移文件,这里才是执行迁移动作
$ flask db upgrade
....
INFO [sqlalchemy.engine.Engine] COMMIT
如果还没有创建数据库和表,这个命令会自动创建;如果已经创建,则会在不损坏数据的前提下执行更新。
提示: 如果你想回滚迁移,那么可以使用downgrade命令(降级),它会撤销最后一次迁移数据库中的改动,这在开发时非常有用。比如,当你执行upgrade命令后发现某些地方出错了,这时就可以执行
flask db downgrade
命令进行回滚,删除对应的迁移脚本,重新生成迁移脚本后再进行更新(upgrade)。
注意:虽然我们更新了数据库,但是之前创建的记录中并没有create_time字段,所以这些记录的create_time字段的值将为空。如果你需要为旧的数据添加默认的create_time字段值,可以手动操作。
本节只是对数据库迁移做一个简单的介绍,你可以阅读Alembic的文档了解更多用法和自定义选项,其中的入门教程(http://alembic.zzzcomputing. com/en/latest/tutorial.html)值得一读。