我对这个问题尝试了很多扭曲,试图弄清楚到底发生了什么。
My SQLAlchemy 代码将表指定为 schema.table。我有一个特殊的连接对象,如果数据库是 PostgreSQL 或 Oracle,则使用指定的连接字符串进行连接,但如果数据库是 SQLite,它会连接到 :memory: 数据库,然后使用架构名称附加 SQLite 基于文件的数据库。这使我可以在整个 SQLAlchemy 代码中使用架构名称,而不会出现任何问题。
但是当我尝试设置 Alembic 来查看我的数据库时,它完全失败了。我做错了什么?
最佳答案
在开始这项工作之前,我遇到了几个必须解决的问题。
最初,Alembic 根本看不到我的数据库。如果我尝试在 alembic.ini 文件中指定它,它将使用默认架构加载 SQLite 数据库,但我的模型代码指定了一个架构,因此这不起作用。我必须更改 run_migrations_online()
中的 alembic/env.py
才能从代码中调用我的连接方法,而不是使用 engine_from_config
。就我而言,我创建了一个数据库对象,该对象具有一个 connect()
方法,该方法将返回引擎
和元数据
。我将其称为“可连接的,meta = db.connect()”。我将使用 schema=db.schema()
返回模式名称。我必须从 SQLAlchemy 代码中导入 db
类才能访问这些内容。
现在我正在进行迁移,该迁移将从头开始构建整个数据库,但我无法运行该迁移,因为我的数据库已经进行了这些更改。显然 Alembic 没有看到我的数据库。 Alembic 还一直告诉我我的数据库已经过时了。那里的问题是 alembic 表 alembic_version
正在被写入我的 :memory:
数据库,一旦连接被删除,数据库也会被删除。因此,为了让 Alembic 记住迁移,我需要在数据库中创建该表。我向 env.py
添加了更多代码,以使用 version_table_schema=my_schema
将架构传递给 context.configure
。
当我再次生成迁移时,我仍然得到了从头开始构建数据库的迁移,因此 Alembic 仍然看不到我的数据库。经过更多的谷歌搜索后,我发现我需要将 include_schemas=True
传递给 env.py
中的 context.configure
。但添加后,我开始从 Alembic 获取回溯。
幸运的是,我的配置已设置为提供连接和元数据。通过将 target_metadata=target_metadata
行更改为 target_metadata=meta
(我从连接返回的本地元数据),我也绕过了这些回溯,并且 Alembic 开始正常运行。
回顾一下,为了让 Alembic 使用作为模式名称附加的 SQLite 数据库,我必须导入用于 Flask 代码的连接脚本。该连接脚本正确附加 SQLite 数据库,然后反射(reflect)元数据。它返回引擎和元数据。我将引擎返回到 env.py 中的“可连接”变量,并将元数据返回到新的局部变量 meta。我还将架构名称返回到局部变量架构。
在 with connectable.connect() as connection: block 中,我将附加参数传递给 context.configure target_metadata=meta
、version_table_schema=schema
和 include_schemas=True
其中元和架构是我上面设置的新局部变量。
通过所有这些更改,我认为我能够使用作为架构附加的 SQLite 数据库。不幸的是,我继续遇到这方面的问题,并最终决定我根本不会将 SQLite 与 Alembic 一起使用。我们现在的规则是 Alembic 迁移仅适用于非 SQLite 数据库,并且在尝试 Alembic 数据迁移之前必须将 SQLite 数据迁移到另一个数据库。
我正在记录这一点,以便其他面临此问题的人能够遵循我所做的事情,并可能让 Alembic 为 SQLite 工作。
关于python - 如何为作为架构附加的 SQLite 数据库设置 Alembic?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67083616/