Alembic 使用现有的 SQLAlchemy 引擎迁移

Alembic migrate with existing SQLAlchemy engine

我有一个在 sqlite 内存数据库上创建的特定 SQLAlchemy 声明性基础:

engine = create_engine('sqlite:///:memory:')
Base.metadata.create_all(engine)

我将其用于单元测试逻辑。

有了这个,我在数据库中有了我的表。但现在我想使用 alembic 迁移某些东西。

AFAIK alembic 迁移使用 env.py run_migrations_online 并使用名为 engine_from_config 的 SQLAlchemy 函数在此处创建一个新引擎。

我想解决的问题是有一种方法可以使用先前创建的连接,其中包含最近创建的表,用于 alembic 迁移。

我在我的测试脚本中使用了这个:Using Alembic API from inside application code,所以我的脚本在之前的 create_all 调用之后执行以下操作:

import alembic.config
alembicArgs = ['--raiseerr', '-x', 'dbPath=sqlite:///:memory:', 'upgrade', 'head']
alembic.config.main(argv=alembicArgs

[请注意,我只是通过 Base.metadata.create_all(engine) 调用创建我的模式,但我的 alembic 版本不仅包含模式更改,它们还填充了一些目录表数据,这就是我打算使用 alembic 的原因这里。事实上,如果我的 alembic 迁移包含一些 "create tables" 逻辑,这两者就会发生冲突。所以我可以安全地删除 create_all 调用并单独依赖 alembic 在这里创建我的模式。]

已经修改了我的 alembic env.py:

def run_migrations_online():
    ini_section = config.get_section(config.config_ini_section)

    db_path = context.get_x_argument(as_dictionary=True).get('dbPath')

    if db_path:
        ini_section['sqlalchemy.url'] = db_path

    connectable = engine_from_config(
        ini_section,
        prefix ... # everything from here the same as default env.py

据我所知,connectable=engine_from_config 在新的 sqlite:///:memory: 数据库上创建了到新引擎的连接,这就是为什么我无法通过 alembic 升级之前在我的数据库上创建的数据库create_all(engine).

脚本

所以... TLDR;有没有办法将我以前存在的引擎连接(使用我创建的表)传递给 alembic,以便它可以迁移它? (我很确定我创建的 dbPath arg 在这里没有用,事实上,我只是复制我引用的其他 post 使用的内容)。

您可以创建一个 alembic 配置实例并对其进行操作:

def migrate_in_memory(migrations_path, alembic_ini_path=None, connection=None, revision="head"):
    config = alembic.config.Config(alembic_ini_path)
    config.set_main_option('script_location', migrations_path)
    config.set_main_option('sqlalchemy.url', 'sqlite:///:memory:')
    if connection is not None:
        config.attributes['connection'] = connection
    alembic.command.upgrade(config, revision)

它可能需要一些微调,但这是事情的一般要点。