在开发程序的过程中,你会发现有时需要修改数据库模型,而且修改之后还需要更新数据库。仅当数据库表不存在时,Flask-SQLAlchemy 才会根据模型进行创建。因此,更新表的唯一方式就是先删除旧表,不过这样做会丢失数据库中的所有数据。更新表的更好方法是使用数据库迁移框架。源码版本控制工具可以跟踪源码文件的变化,类似地,数据库迁移框架能跟踪数据库模式的变化,然后增量式的把变化应用到数据库中
这个模块需要我们单独安装
pip install flask_migrate
使用方法也很简单
使用原本实例化的app对象作为参数实例化migrate对象,并绑定migrate命令
migrate = Migrate(app, db) manager.add_command('db', MigrateCommand)
使用方法如下
usage: Perform database migrations Perform database migrations positional arguments: {init,revision,migrate,edit,merge,upgrade,downgrade,show,history,heads,branches,current,stamp} init Creates a new migration repository revision Create a new revision file. migrate Alias for 'revision --autogenerate' edit Edit current revision. merge Merge two revisions together. Creates a new migration file upgrade Upgrade to a later version downgrade Revert to a previous version show Show the revision denoted by the given symbol. history List changeset scripts in chronological order. heads Show current available heads in the script directory branches Show current branch points current Display the current revision for each database. stamp 'stamp' the revision table with the given revision; don't run any migrations optional arguments: -?, --help show this help message and exit
我们需要先初始化
python manager.py db init
然后进行数据迁移
python manager.py db migrate
最后进行更新
python manager.py db upgrade
经过以上操作会发现项目目录下多了migrations文件夹,然后versions下面有生成一个迁移脚本,我们来看看内容
"""empty message Revision ID: 4c75713ac6d1 Revises: Create Date: 2019-09-26 10:12:43.860922 """ from alembic import op import sqlalchemy as sa from sqlalchemy.dialects import mysql # revision identifiers, used by Alembic. revision = '4c75713ac6d1' down_revision = None branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column('network', sa.Column('item_id', sa.Integer(), autoincrement=True, nullable=False)) op.drop_column('network', 'nid') op.add_column('network_detail', sa.Column('item_id', sa.Integer(), nullable=True)) op.create_index(op.f('ix_network_detail_item_id'), 'network_detail', ['item_id'], unique=False) op.drop_index('ix_network_detail_nid', table_name='network_detail') op.drop_column('network_detail', 'nid') op.add_column('system', sa.Column('item_id', sa.Integer(), autoincrement=True, nullable=False)) op.drop_column('system', 'sid') op.add_column('system_detail', sa.Column('item_id', sa.Integer(), nullable=True)) op.create_index(op.f('ix_system_detail_item_id'), 'system_detail', ['item_id'], unique=False) op.drop_index('ix_system_detail_sid', table_name='system_detail') op.drop_column('system_detail', 'sid') # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### op.add_column('system_detail', sa.Column('sid', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True)) op.create_index('ix_system_detail_sid', 'system_detail', ['sid'], unique=False) op.drop_index(op.f('ix_system_detail_item_id'), table_name='system_detail') op.drop_column('system_detail', 'item_id') op.add_column('system', sa.Column('sid', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False)) op.drop_column('system', 'item_id') op.add_column('network_detail', sa.Column('nid', mysql.INTEGER(display_width=11), autoincrement=False, nullable=True)) op.create_index('ix_network_detail_nid', 'network_detail', ['nid'], unique=False) op.drop_index(op.f('ix_network_detail_item_id'), table_name='network_detail') op.drop_column('network_detail', 'item_id') op.add_column('network', sa.Column('nid', mysql.INTEGER(display_width=11), autoincrement=True, nullable=False)) op.drop_column('network', 'item_id') # ### end Alembic commands ###
这个脚本就是我们自动迁移生成的数据迁移脚本
注意自动迁移会漏掉一些细节,例如我的修改了主键,然后自动迁移后主键字段没有被设为主键
可以的话自己使用revision 命令手动创建Alembic 迁移