我正在使用Alembic来处理Flask的迁移 . 理论上, alembic revision --autogenerate
应根据数据库中的更改自动生成迁移 . 但是,Alembic只是使用上述命令生成空白迁移 .
有一个question very similar to this one,其中的问题是没有导入正确的模型 . 但是,我从Flask应用程序导入了模型,如 env.py
所示:
...
# import settings from Flask
alembic_config = config.get_section(config.config_ini_section)
from start import app
from models import User, Item, Recipient # models are imported here from models.py
alembic_config['sqlalchemy.url'] = app.config['SQLALCHEMY_DATABASE_URI']
engine = engine_from_config(
alembic_config, # config.get_section(config.config_ini_section)
prefix='sqlalchemy.',
poolclass=pool.NullPool)
...
以及 env.py
中导入的db元数据('start'是我的Flask应用程序主文件的名称):
...
from start import db
target_metadata = db.metadata
...
运行 alembic revision --autogenerate -m "initial_rev"
然后生成一个空迁移,虽然我的Flask应用程序会有所不同:
"""initial_rev
Revision ID: 45296fd29540
Revises: None
Create Date: 2013-06-19 17:32:38.392268
"""
# revision identifiers, used by Alembic.
revision = '45296fd29540'
down_revision = None
from alembic import op
import sqlalchemy as sa
def upgrade():
### commands auto generated by Alembic - please adjust! ###
pass
### end Alembic commands ###
def downgrade():
### commands auto generated by Alembic - please adjust! ###
pass
### end Alembic commands ###
编辑
Here is a gist显示我的应用程序的文件结构,以及一些其他代码 . 似乎问题是Alembic不喜欢从 database.py
导入数据库而没有在 __init__.py
中首先进行初始化 . 但是,当使用蓝图时(由于循环导入),这是不可能的,在本SO答案中解释:https://stackoverflow.com/a/9695045/353878 .
所以问题是,当使用Flask蓝图时,如何使用Alembic?
编辑#2
我甚至尝试打印 db.metadata.sorted_tables
,以确保正确导入数据库元数据 . 果然,整个数据库架构被传送到终端 . 那么为什么Alembic会产生空白的升级/降级功能呢?
编辑#3
我已经得出结论,这个问题与 db.init_app(app)
和 db = SQLAlchemy(app)
的差异有关,但我不太确定导致这个问题的原因 . 为了测试这个理论,我将 env.py
中的 from database import db
替换为 db = SQLAlchemy(app)
. 可能是一个坏主意,但我想看看调试目的会发生什么 .
Alembic自动生成并填充了upgrade()和downgrade()方法 - 除了它们被颠倒了! upgrade()
删除了我的所有三个表,而 downgrade()
用所有正确的列和元数据创建了它们 . 我不知道为什么会这样,但我希望它对试图解决这个问题的人有所帮助 .
1 回答
以下是我如何使用Alembic和Flask以及蓝图 .
https://github.com/davidism/basic_flask
我使用应用程序工厂模式并在其中调用
db.init_app
. 在db = SQLAlchemy()
之后,我导入所有将继承db.Model
的模型,以便db.metadata
知道它们;请注意,这不是在create_app
工厂中完成的,而是在模块初始化期间内联 .运行
alembic
时,项目文件夹不包含在sys.path
中,所以我进行了设置 . 然后我从工厂创建一个应用程序,并从其配置中设置sqlalchemy.url
. 另外,我导入db
并设置target_metadata = db.metadata
.无论项目结构如何,此设置始终适用于我 . 我在一个包含蓝图的子包中包含了一组非常基本的用户模型和一个非常愚蠢的视图 . 只需确保在
load_models
中加载相关模型,在定义蓝图后导入视图,然后在init_views
中导入蓝图 .