在开发过程中,需要修改数据库模型,而且还要在修改之后更新数据库。最直接的方式就是删除旧表,但这样会丢失数据。更好的解决办法是使用数据库迁移框架,它可以追踪数据库模式的变化,然后把变动应用到数据库中。在Flask中可以使用Flask-Migrate扩展,来实现数据迁移。并且集成到Flask-Script中,所有操作通过命令就能完成。为了导出数据库迁移命令,Flask-Migrate提供了一个MigrateCommand类,可以附加到flask-script的manager对象上。
1、安装Flask-Migrate
pip install flask-migrate
2、代码
from flask import Flask
from flask_migrate import Migrate
from flask_script import Manager
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
# 使用Manager 管理 flask 应用
manager = Manager(app)
app.debug = True
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql://root:512279csx@127.0.0.1:3306/'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
app.config['SQLALCHEMY_BINDS'] = False
db = SQLAlchemy(app)
# 第一个参数是Flask 实例,第二个参数是SQLAlchemy实例模型
migrate = Migrate(app,db)
# 添加一个命令,这里的db 可以随便起和前面的SQLAlchemy对象没有关系,不过大家都习惯使用db
manager.add_command('db',MigrateCommand)
class User(db.Model):
__tablename__ = 'user'
id = db.Column(db.Integer,primary_key=True)
name = db.Column(db.String(32),unique=True)
@app.route('/')
def index():
return 'hello world'
if __name__ == '__main__':
manager.run()
3、数据库迁移
数据库迁移初始化:
python manager.py db init
说明:
- 执行上面命令前要先运行代码
- manager.py 是你的写上面代码的文件名,后面的都是
- 这里的db 是你在: manager.add_command(’ db ',MigrateCommand) 里添加的命令
创建迁移脚本
python manager.py db migrate -m 'first_migrate'
说明:执行完这个命令还没生成我们需要的数据库,还需执行下面的代码。
更新数据库:
python manager.py db upgrade
当你修改表的字段之后执行:创建迁移脚本 和 更新数据库就可以了
查询版本号
python manager.py db history
输出格式:<之前的版本> -> 当前版本号 (head), initial migration
版本回滚
python manager.py db downgrade 版本号
当你执行上面命令的时候,可能会报错,
出现这种错误的时候,那是因为你的 迁移版本中的downgrade() 方法中出了错误。**这里是因为我们增加email 字段的时候,添加了唯一性约束,但是在删除字段的时候,要先删除唯一性约束。**当然版本回滚时,若是出错了,你就需要去改改downgrade() 方法中的代码了。
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
# 给数据表添加一个字段
op.add_column('users', sa.Column('email', sa.String(length=32), nullable=True))
# 给字段添加唯一性约束
op.create_unique_constraint(None, 'users', ['email'])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'users', type_='unique')
# 删除email 列
op.drop_column('users', 'email')
修改代码如下:
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
# 给数据表添加一个字段
op.add_column('users', sa.Column('email', sa.String(length=32), nullable=True))
# 给字段添加唯一性约束
op.create_unique_constraint(None, 'users', ['email'])
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
# 修改这里,删除唯一性约束,
op.drop_constraint('email', 'users', type_='unique')
# 删除email 列
op.drop_column('users', 'email')