如何用SQLAlchemy+Alembic创建foo schema迁移?Flask-Migrate场景
解决Flask-Migrate中缺失foo schema导致的迁移失败问题
遇到这个问题很常见,因为Alembic默认不会自动检测并创建数据库schema(PostgreSQL中的概念,MySQL中对应database)。下面是两种可靠的解决方法,推荐用第一种通过迁移脚本管理schema的方式,因为它符合版本控制的最佳实践:
方法一:手动创建包含schema创建逻辑的迁移脚本
这是最规范的做法,把schema的创建纳入迁移版本管理中:
生成空的迁移脚本
在终端执行命令:# 如果用flask命令 flask db migrate -m "Create foo schema and my_table" # 如果用manage.py python manage.py db migrate -m "Create foo schema and my_table"这会在
migrations/versions目录下生成一个新的迁移文件。编辑迁移文件,添加schema创建逻辑
打开生成的迁移文件,修改upgrade()和downgrade()函数,确保先创建schema再创建表,删除时先删表再删schema(删除schema可选,避免影响其他使用该schema的表)。以PostgreSQL为例:
def upgrade(): # 先创建foo schema,加上IF NOT EXISTS避免重复创建报错 op.execute('CREATE SCHEMA IF NOT EXISTS foo;') # 下面是Alembic自动生成的my_table创建代码(注意schema参数已自动带上) op.create_table('my_table', sa.Column('id', sa.Integer(), nullable=False), sa.Column('name', sa.Text(), nullable=False), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('name'), schema='foo' ) def downgrade(): # 先删除foo schema下的my_table op.drop_table('my_table', schema='foo') # 可选:如果确定没有其他表使用foo schema,再删除它 op.execute('DROP SCHEMA IF EXISTS foo;')如果你用的是MySQL,schema等同于database,把SQL语句换成:
op.execute('CREATE DATABASE IF NOT EXISTS foo;') # 降级时 op.execute('DROP DATABASE IF EXISTS foo;')执行迁移
再次运行升级命令:flask db upgrade # 或 python manage.py db upgrade
方法二:通过SQLAlchemy事件监听自动创建schema(应急方案)
如果你希望每次应用连接数据库时自动检查并创建foo schema,可以在你的Flask应用初始化代码中添加事件监听:
from sqlalchemy import event from sqlalchemy.engine import Engine @event.listens_for(Engine, "connect") def create_schema_on_connect(dbapi_connection, connection_record): cursor = dbapi_connection.cursor() # 同样根据数据库类型调整SQL语句 cursor.execute('CREATE SCHEMA IF NOT EXISTS foo;') cursor.close()
这种方法不需要修改迁移脚本,但缺点是schema的创建没有纳入版本管理,团队协作时容易出现不一致,所以只推荐作为临时应急方案。
内容的提问来源于stack exchange,提问作者s5s
相关产品推荐
相关产品推荐

