【问题标题】:How to run post upgrade code in alembic upgrade head如何在 alembic 升级头中运行升级后代码
【发布时间】:2019-12-11 21:26:06
【问题描述】:

我正在修改一个模型(添加一个新列)并且我有一个相应的迁移文件。我的目标是通过向新列添加一些数据来扩展此迁移。

我尝试通过添加我自己的 sql 代码来修改迁移文件以实现我的目标。修改后的 almebic 文件示例包含如下代码:

# below is the only line added by alembic
op.add_column('sample_table', sa.Column('new_column', sa.UnicodeText(), nullable=True))
# below lines are my own
my_obj = MyClass()
table_item = my_obj.get_table_item(some_parameter)
...
...

问题是我的函数“get_table_item”在同一个表上运行,与 alembic 在“op.add_column”行中运行的表相同。由于 alembic 在 alembic 升级期间锁定了表,因此我的函数“get_table_item”会因为这个锁而被卡住。 有什么方法可以在不修改我的函数“get_table_item”的情况下实现我的目标?

【问题讨论】:

  • 两次迁移。一来修改架构,二来添加数据。
  • 您的想法似乎不错。但是如何在一个“alembic 升级头”中运行两个迁移?
  • 当您使用alembic upgrade head 时,Alembic 将运行它尚未运行的任何迁移,直到它到达链的末尾。查看从 Create a Migration Script 到“运行我们的第二次迁移”的教程,注意迁移脚本是如何链接的。
  • 如果是这种情况,那么当我点击“alembic 升级头”时,为什么我会收到“my_new_colunn”不存在的错误。目前我有两个迁移。第一个是添加一个新列,第二个(最新的)是向它添加数据。
  • 尝试依次运行每个迁移。结果不一样吗?

标签: python postgresql database-migration pyramid alembic


【解决方案1】:

编写 Alembic 迁移脚本需要牢记的一件重要事情是,它们不仅需要与当前应用程序代码一起工作,而且还需要与它的所有未来版本一起工作。您的示例看起来像是从应用程序代码中导入映射类并尝试运行一些依赖于新添加列的方法:

from haris_awesome_app import MyClass
# below is the only line added by alembic
op.add_column('sample_table', sa.Column('new_column', sa.UnicodeText(), nullable=True))
# below lines are my own
my_obj = MyClass()
table_item = my_obj.get_table_item(some_parameter)

这将在您将来向get_table_item 添加新参数、重命名MyClass 甚至更改导入结构时产生问题。

更好的方法是完全包含 Alembic 迁移步骤,即迁移成功所需的一切都应该在迁移文件本身中。您可以使用op.execute 在迁移文件中运行任意 SQL:

def upgrade():

    op.add_column('sample_table', sa.Column('new_column', sa.UnicodeText(), nullable=True))

    op.execute('''UPDATE sample_table SET new_column = ...''')

这里有一些 documentation on op.execute 以及更多示例。

【讨论】:

    猜你喜欢
    • 2014-04-01
    • 2019-08-14
    • 1970-01-01
    • 2020-06-10
    • 2020-12-06
    • 2015-03-31
    • 1970-01-01
    • 2020-12-22
    • 1970-01-01
    相关资源
    最近更新 更多