【问题标题】:How to write portable Boolean columns for Alembic如何为 Alembic 编写可移植的布尔列
【发布时间】:2021-07-06 22:23:17
【问题描述】:

我正在开发一个 Flask 应用程序,使用 Flask-Migrate(以及 Alembic)来管理对数据库的更改。我很早就遇到了一个问题,即更改一些 not-nullable 布尔列在底层数据库中引发了错误。

我正在删除一个布尔列,并重命名另一个(相当于两次删除和一次添加)。

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.add_column('user', sa.Column('is_enabled', sa.Boolean(), nullable=False))
    op.drop_column('user', 'is_disabled')
    op.drop_column('user', 'is_deleted')
    # ### end Alembic commands ###

由于数据库中已经有数据,添加需要一个默认值来用于现有的行。但是,SQLAlchemy 的人有 already passed 在布尔列中添加(便携式)对 server_default 的支持。

鉴于这些条件,有没有办法进行这种迁移并保持数据库的可移植性,或者我是否需要将代码限制在一个数据库中,并开始根据布尔列的底层 DB 驱动程序编码 server_default 值?

【问题讨论】:

    标签: python sqlalchemy alembic flask-migrate


    【解决方案1】:

    是的,您可以更改升级(可能还有降级)功能来实现您想要的。另请注意,您当前的升级不会保留现有数据,因为您正在添加新列并删除旧列。由于 alembic 无法检测到重命名,您需要更改升级(和降级)自动生成的函数。

    通过回填数据库来实现您想要的:

    • 添加/重命名不带nullable 约束的列。
    • 当当前值为Null 时,使用默认值回填现有行。
    • 更改列以包含nullable 约束:

    要解决重命名问题,您需要将添加和删除行更改为 1 个更改行:

    def upgrade():
        # ### commands auto generated by Alembic - please adjust! ###
        op.alter_column('user', 'is_disabled', new_column_name='is_enabled')
        op.execute('update user set is_disabled=false where is_disabled is null')
        op.alter_column('user', 'is_enabled', nullable=False)
        op.drop_column('user', 'is_deleted')
        # ### end Alembic commands ###
    

    此外,当您将 is_disabled 更改为 is_enabled 时,如果需要,您可以使用 op.execute 切换布尔值。

    【讨论】:

      猜你喜欢
      • 2021-11-14
      • 1970-01-01
      • 1970-01-01
      • 2013-10-02
      • 1970-01-01
      • 1970-01-01
      • 2013-01-10
      • 2023-01-24
      • 1970-01-01
      相关资源
      最近更新 更多