更新模型导致Alembic历史迁移执行失败如何解决?
问题根因
报错的核心原因是第二个迁移脚本直接引用了当前最新版本的MyModel ORM类,该ORM类已经包含第三个迁移才会新增的my_other_model_id字段,SQLAlchemy生成插入SQL时会自动带上该字段,而第二个迁移执行时表中还没有这个字段,因此触发字段不存在的错误。
可行解决方案
方案1:使用SQLAlchemy Core执行插入(官方推荐最佳实践)
Alembic官方建议迁移脚本中不要依赖全局ORM类,避免ORM版本和迁移执行时的表结构不匹配,直接用Core构造明确指定字段的插入语句即可:
# 修改后的第2个迁移脚本 def upgrade(): op.execute( sa.text("INSERT INTO my_model (id, text) VALUES (:id, :text)") .bindparams(id=1, text='text') )
也可以在迁移内单独定义对应版本的表结构执行批量插入:
def upgrade(): # 仅定义当前迁移执行时my_model表存在的字段 my_model_table = sa.Table( 'my_model', sa.MetaData(), sa.Column('id', sa.Integer(), nullable=False), sa.Column('text', sa.Text()) ) op.bulk_insert(my_model_table, [{'id': 1, 'text': 'text'}])
方案2:ORM插入时明确指定要写入的字段
如果需要保留ORM写法,可以在提交时明确排除不存在的字段,仅指定当前表存在的字段:
# 修改后的第2个迁移脚本 def upgrade(): my_model = MyModel(id=1, text='text') session.add(my_model) # 提交时仅指定已存在的字段,跳过后续才会新增的my_other_model_id session.flush(include_properties=['id', 'text']) session.commit()
方案3:调整迁移执行顺序
如果业务逻辑允许,你可以修改迁移脚本的版本号,将插入数据的第二个迁移调整到第三个迁移之后执行,插入数据时my_other_model_id字段已经存在,就不会触发报错。该方案仅适合插入逻辑不依赖初始表结构的场景。
内容的提问来源于stack exchange,提问作者Jim Jeffries
相关产品推荐
相关产品推荐

