我有一个非常标准的烧瓶应用程序。它使用
flask_sqlalchemy
管理与 postgres
服务器的连接,并使用 alembic
管理迁移。
现在的问题是我正在将它与另一个项目集成,这意味着我试图允许它从另一个数据库中提取单个模型。幸运的是,
flask_sqlalchemy
通过 SQLALCHEMY_BINDS
标志对此提供了大力支持。所以我的应用程序设置了一个新模型,如下所示:
class CoreUser(UserMixin, db.Model):
__bind_key__ = 'core'
id = db.Column(db.Integer, primary_key=True)
email = db.Column(db.String(255), unique=True)
到目前为止一切顺利。我的应用程序现在在应该时检查另一个数据库。但这是缺点。由于我使用
alembic
来实际管理数据库中的所有模式,因此当我运行典型的 alembic revision --autogenerate
脚本时,它实际上根本不会对第二个数据库执行任何操作,并且似乎只是忽略了 __bind_key__
拼图的一部分。
相反,它在第一个数据库中设置正确的
core_user
关系。我如何向 alembic 表明,当它遇到此模式定义时,它应该在不同的数据库中创建关系?
我已经尝试根据
this(古代)线程的建议更新我的
alembic.ini
文件,如下所示:
[core_db]
sqlalchemy.url = <DATABASE_URI>
script_location = alembic
然后运行以下命令:
alembic -n core_db revision --autogenerate
alembic -n core_db upgrade head
虽然生成了修订版本并且不会失败,但在数据库中实际没有创建由
core_db
sqlalchemy.url
参数指示的关系。
我找不到比 4 年前的 Google 小组帖子更好的文档,但我目前的方法似乎不起作用,而且我没有任何明显的后续步骤。我无法找到适当的
alembic
文档,但这似乎是一个非常简单且常见的用例,所以我无法想象这不受支持。
有什么建议吗?
很难处理许多数据库和不同模型的迁移。
在我们的例子中,我们有 N 个具有不同模型的数据库。以下结构有助于保持数据库隔离:
.
├── app
│ ├── __init__.py
│ ├── alembic.ini
│ ├── employee
│ │ ├── __init__.py
│ │ ├── models.py
│ │ └── views.py
│ ├── migrations
│ └── user
│ ├── __init__.py
│ ├── models.py
│ └── views.py
├── daemon
│ ├── __init__.py
│ ├── alembic.ini
│ ├── daemon_engine.py
│ ├── migrations
│ └── models.py
├── run.py
└── tests
您到目前为止所采取的步骤是正确的。
但是,您是否为每个数据库在
target_metadata
中分配了正确的 env.py
?
如果传入的元数据对于两个数据库相同,则不会找到不同的关系,因此自动生成的脚本将不会反映您正在查找的内容。
通过查看
Base.metadata.tables
变量来检查哪些表与元数据关联。
仅传入每个数据库所需的表
env.py
。每个数据库都应该在各自的script_location
中拥有一个。
我通过使用
flask-sqlalchemy
及其 alembic
选项,使其与 flask-migrate
和 --multidb
一起使用:
https://flask-migrate.readthedocs.io/en/latest/#multiple-database-support
然后我必须修改所有旧的数据库迁移(当我只有一个数据库时),如此处所述:
https://github.com/miguelgrinberg/Flask-Migrate/issues/181
升级脚本仍然遇到一些麻烦,因为它向这个新数据库添加和删除了我的所有旧表。不确定那是什么,但很快就会知道...
这很难。使用自动生成功能创建新修订版时,Alembic(从
v1.11.3
开始)通过将ONLY连接到版本表的单个数据库来检查历史记录,并通过访问文件夹中的所有脚本文件来提取所有头 migrations/versions
(假设只有一个版本路径)。
换句话说,Alembic 始终假设每个迁移文件夹只有一个数据库。将第二次(或后续)迁移升级到其中一个数据库时,您将收到错误
对于那些对实现细节感兴趣的人,请查看以下功能: