我正在使用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
中导入的数据库元数据('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?
我甚至尝试打印db.metadata.sorted_tables
,以确保正确导入数据库元数据。果然,整个数据库架构被传送到终端。那么为什么Alembic会产生空白的升级/降级功能呢?
我的结论是,该问题与db.init_app(app)
和db = SQLAlchemy(app)
的差异有关,但我不确定是什么导致了这个问题。为了验证这一理论,我将from database import db
中的env.py
替换为db = SQLAlchemy(app)
。可能是一个坏主意,但我想看看调试目的会发生什么。
Alembic自动生成并填充了upgrade()和downgrade()方法 - 除了它们被颠倒了! upgrade()
删除了我的所有三个表,而downgrade()
使用所有正确的列和元数据创建了它们。我不知道为什么会这样,但我希望这对试图解决这个问题的人有所帮助。
答案 0 :(得分:25)
以下是我如何将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
中导入蓝图。