我正在使用Alembic处理Flask的迁移。alembic revision --autogenerate理论上,应该基于数据库中的更改自动生成迁移。但是,Alembic仅使用上述命令即可生成空白迁移。
alembic revision --autogenerate
有一个与此问题非常相似的问题,即问题是没有导入正确的模型。但是,我已经从我的Flask应用程序导入了模型,如下所示env.py:
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 ###
编辑 这里的要点显示了我的应用程序的文件结构,以及一些其他代码。看来问题在于,Alembic不喜欢在database.py不首先初始化的情况下从中导入数据库__init__.py。但是,当使用蓝图时(由于周期性导入),这是不可能的,对此SO答案进行了解释:https : //stackoverflow.com/a/9695045/353878。
database.py
__init__.py
所以问题是,当同时使用烧瓶蓝图时,如何使用Alembic?
编辑#2 我什至尝试打印db.metadata.sorted_tables,以确保正确导入了数据库元数据。可以肯定的是,整个数据库模式已通过管道传输到终端。那么,为何Alembic会生成空白的升级/降级功能?
db.metadata.sorted_tables
编辑#3 我的结论是,这个问题有什么做的分歧db.init_app(app)和db = SQLAlchemy(app),但我不能肯定是什么原因造成的问题。为了验证这一理论,我更换from database import db的env.py是db = SQLAlchemy(app)。可能是个坏主意,但我想看看出于调试目的会发生什么。
db.init_app(app)
db = SQLAlchemy(app)
from database import db
Alembic自动生成并填充了upgrade()和downgrade()方法-除非它们被反转了!upgrade()删除了我的所有三个表,同时downgrade()使用所有适当的列和元数据创建了它们。我不知道为什么会这样,但是我希望它对尝试解决此问题的人们有所帮助。
了upgrade()
downgrade()
upgrade()
downgrade()
我使用应用程序工厂模式并db.init_app在其中调用。之后db = SQLAlchemy()我导入,将继承所有车型db.Model,从而db.metadata知道他们的; 请注意,这不是在create_app工厂完成的,而是在模块初始化期间内联的。
db.init_app
db = SQLAlchemy()
db.Model
db.metadata
create_app
运行时alembic,项目文件夹不包括在内,sys.path因此我进行了设置。然后,我从工厂创建一个应用,并sqlalchemy.url根据其配置进行设置。另外,我导入db并设置target_metadata = db.metadata。
alembic
sys.path
sqlalchemy.url
db
target_metadata = db.metadata
无论项目结构如何,此设置始终对我有效。我在带有蓝图的子包中包含了一组非常基本的用户模型和一个非常愚蠢的视图。只需确保将relavent模型加载到中load_models,在定义了蓝图之后导入视图,并在中导入蓝图init_views。
relavent
load_models
init_views