覆盖 alembic env.py 文件中的值

Override values in alembic env.py file

我正在使用 alembic 进行数据库修订,这可能与预期的差不多。我没有在 alembic.ini 中定义数据库字符串,而是使用 env.py 文件从配置模块动态获取数据库凭据,大致如下:

SQLALCHEMY_DATABASE_URL = "%s://%s:%s@%s:%d/%s" % (settings.db_type, settings.db_username, settings.db_password, settings.db_host, settings.db_port, settings.db_database)

def run_migrations_online():
    """Run migrations in 'online' mode.

    In this scenario we need to create an Engine
    and associate a connection with the context.

    """
    connectable = create_engine(SQLALCHEMY_DATABASE_URL)

    with connectable.connect() as connection:
        context.configure(
            connection=connection, target_metadata=target_metadata
        )

        with context.begin_transaction():
            context.run_migrations()

现在的问题是我正在添加 pytest 测试,这些测试使用单独的数据库连接。基本上我正在做的是创建一个数据库,应用迁移,添加测试数据,运行 测试,删除数据库。

在 pytest 中,我按如下方式使用它:

@pytest.fixture(scope="session")
def initialize_database(create_database):
    
    """
    Executes all alembic versions against the empty database to get the general structure up and running.

    No need to yield / delete as the entire database is deleted anyway as part of the `create_database` yield fixture
    """
    # retrieves the directory that *this* file is in
    root_dir = os.path.dirname(os.path.dirname(os.path.dirname(os.path.realpath(__file__))))
    # this assumes the alembic.ini is also contained in this same directory
    config_file = os.path.join(root_dir, "alembic.ini")
    migrations_dir = os.path.join(root_dir, "alembic")

    config = Config(file_=config_file)
    config.set_main_option("script_location", migrations_dir)
    command.upgrade(config, 'head')

我试图在此处指定不同的数据库凭据,但 env.py 中的值覆盖了它。如何在这样的设置中指定不同的数据库凭据?

我自己找到了解决办法,其实很简单。从测试夹具调用 upgrade 命令时,我设置了两个额外的配置值,如下所示:

config.set_main_option("is_testing", "True")
config.set_main_option('sqlalchemy.url', SQLALCHEMY_DATABASE_URL)

env.py 文件中,我可以使用此测试选项动态更改 SQLAlchemy url,如下所示:

SQLALCHEMY_DATABASE_URL = "%s://%s:%s@%s:%d/%s" % (settings.db_type, settings.db_username, settings.db_password, settings.db_host, settings.db_port, settings.db_database)

if config.get_main_option("is_testing", "False") == "True":
    url = config.get_main_option("sqlalchemy.url")
else:
    url = SQLALCHEMY_DATABASE_URL

这样效果很好。