0

我在这个问题上尝试了很多扭曲来试图弄清楚发生了什么。

我的 SQLAlchemy 代码将表指定为 schema.table。如果数据库是 PostgreSQL 或 Oracle,我有一个特殊的连接对象,它使用指定的连接字符串进行连接,但如果数据库是 SQLite,它会连接到一个 :memory: 数据库,然后使用模式名称附加基于 SQLite 文件的数据库。这使我可以毫无问题地在我的 SQLAlchemy 代码中使用模式名称。

但是当我尝试设置 Alembic 来查看我的数据库时,它完全失败了。我究竟做错了什么?

4

1 回答 1

1

在我开始工作之前,我遇到了几个必须解决的问题。

最初,Alembic 根本没有看到我的数据库。如果我试图在 alembic.ini 文件中指定它,它将使用默认模式加载 SQLite 数据库,但我的模型代码指定了一个模式,所以这不起作用。我不得不更改alembic/env.pyrun_migrations_online()从我的代码中调用我的连接方法,而不是使用engine_from_config. 在我的例子中,我创建了一个数据库对象,它有一个connect()方法可以返回enginemetadata. 我称之为connectable, meta = db.connect(). 我会用schema=db.schema(). 我必须从我的 SQLAlchemy 代码中导入db该类才能访问这些。

现在我得到了一个从头开始构建整个数据库的迁移,但我无法运行该迁移,因为我的数据库已经有了这些更改。显然,Alembic 没有看到我的数据库。Alembic 还不断告诉我我的数据库已经过时了。问题在于,alembic 表alembic_version正在写入我的:memory:数据库,并且一旦连接断开,数据库也是如此。所以为了让 Alembic 记住迁移,我需要在我的数据库中创建该表。我添加了更多代码以env.py将架构传递给context.configure使用version_table_schema=my_schema.

当我再次生成迁移时,我仍然得到了从头开始构建数据库的迁移,所以 Alembic 仍然没有看到我的数据库。经过更多的谷歌搜索,我发现我需要传递include_schemas=Truecontext.configurein env.py。但在我添加之后,我开始从 Alembic 获得回溯。

幸运的是,我的配置设置为同时提供连接和元数据。通过将target_metadata=target_metadata行更改为target_metadata=meta(从连接返回的本地元数据),我也绕过了这些回溯,并且 Alembic 开始正常运行。

回顾一下,为了让 Alembic 使用附加为模式名称的 SQLite 数据库,我必须导入用于 Flask 代码的连接脚本。该连接脚本正确附加 SQLite 数据库,然后反映元数据。它返回引擎和元数据。我将引擎返回到 env.py 中的“可连接”变量,并将元数据返回到新的局部变量 meta。我还将模式名称返回给局部变量模式。

在 with connectable.connect() as connection: 块中,然后我传递给 context.configure 附加参数target_metadata=meta, version_table_schema=schemainclude_schemas=True其中 meta 和 schema 是我在上面设置的新局部变量。

通过所有这些更改,我认为我能够使用作为模式附加的 SQLite 数据库。不幸的是,我继续遇到问题,并最终决定我根本不会使用带有 Alembic 的 SQLite。我们现在的规则是 Alembic 迁移仅适用于非 SQLite 数据库,并且在尝试对数据进行 Alembic 迁移之前,必须将 SQLite 数据迁移到另一个数据库。

我正在记录这一点,以便面临此问题的其他任何人都可以遵循我所做的事情,并可能让 Alembic 为 SQLite 工作。

于 2021-04-13T23:30:27.293 回答