使用Flask-SQLAlchemy在Alembic自动生成迁移时未检测到任何更改

Par*_*der 20 sqlalchemy database-migration flask flask-sqlalchemy alembic

我无法让Alembic使用db.Model(Flask-SQLAlchemy)而不是使用(Flask-SQLAlchemy)自动生成从更改到类的候选迁移Base.

我已修改env.py为创建我的Flask应用程序,导入所有相关模型,初始化数据库,然后运行迁移:

...
uri = 'mysql://user:password@host/dbname?charset=utf8'
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = uri
app.config['SQLALCHEMY_ECHO'] = True
db.init_app(app)
with app.test_request_context():
    target_metadata = db.Model.metadata
    config.set_main_option('sqlalchemy.url', uri)
    if context.is_offline_mode():
        run_migrations_offline()
    else:
        run_migrations_online()
...
Run Code Online (Sandbox Code Playgroud)

这种方法工作正常drop_all(),create_all()(例如,重新创建单元测试的测试分贝时),但似乎在这种情况下落空.自动生成的版本脚本始终具有空的升级和降级方法,例如,

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 ###
Run Code Online (Sandbox Code Playgroud)

我的更改包括重命名列,更改列定义,而不仅仅是对索引和外键的更改.

有没有人在那里使用Alembic和Flask-SQLAlchemy?知道我哪里错了吗?

非常感谢!

Mig*_*uel 41

Alembic无法自动检测表或列重命名.默认情况下,它也不会查找列类型更改,但compare_type可以为此启用该选项.

摘自Alembic文档:

默认情况下,Autogenerate将检测:

  • 表格增加,删除.
  • 列添加,删除.
  • 列上可空状态的更改.

Autogenerate可以选择检测:

  • 列类型的更改.如果您compare_type=True打开,将会发生这种情况EnvironmentContext.configure().该功能在大多数情况下运行良好,但默认情况下处于关闭状态,因此可以首先在目标模式上进行测试.它也可以通过传递一个可调用来定制; 有关详细信息,请参阅功能文档.
  • 更改服务器默认值.如果您compare_server_default=True打开,将会发生这种情况EnvironmentContext.configure().此功能适用于简单的情况,但不能始终产生准确的结果.Postgresql后端实际上将针对数据库调用"检测到的"和"元数据"值以确定等效性.默认情况下,该功能处于关闭状态,因此可以首先在目标模式上对其进行测试.像类型比较一样,它也可以通过传递一个可调用来定制; 有关详细信息,请参阅功能文档.

自动生成无法检测到:

  • 表名的更改.这些将作为两个不同表的添加/删除出现,应该手动编辑为名称更改.
  • 列名称的更改.与表名更改一样,这些更改会被检测为列添加/删除对,这与名称更改完全不同.
  • 特殊的SQLAlchemy类型,例如Enum在后端生成时不ENUM直接支持- 这是因为非支持数据库中这种类型的表示,即CHAR+CHECK约束,可以是任何类型CHAR+CHECK.对于SQLAlchemy来说,确定这实际上ENUM只是一个猜测,这通常是一个坏主意.要在此处实现您自己的"猜测"函数,请使用该sqlalchemy.events.DDLEvents.column_reflect()事件来更改为某些列传递的SQLAlchemy类型,并可能sqlalchemy.events.DDLEvents.after_parent_attach()拦截不需要的CHECK约束.

Autogenerate目前无法进行,但最终会检测到:

  • 自由站立约束添加,删除,像CHECK,UNIQUE,FOREIGN KEY-这些都还没有实现.现在你会得到内新表,PK和FK约束约束的"降级"到先前存在的表,以及CHECK与SQLAlchemy的"模式"类型产生的约束Boolean,Enum.
  • 指数增加,删除 - 尚未实施.
  • 序列添加,删除 - 尚未实现.

更新:Alembic 0.7.x版本支持最后一个列表中的一些项目.


Bra*_*d M 6

我的错误是尝试使用已处于最终状态的数据库创建初始迁移,认为它会注意到它没有现有版本并基于模型。我得到了空版本,直到删除了数据库中的所有表,然后它工作正常。

  • @cal97g close:需要在预迁移的数据库上_生成_迁移 (2认同)

Gof*_*tty 6

我也遇到了这个问题并使用以下方法解决:

打开migrations/env.py文件,然后在def run_migrations_online()函数上查看context.configureAlembic 1.0.8它应该如下所示:

with connectable.connect() as connection:
    context.configure(
        connection=connection,
        target_metadata=target_metadata,
        process_revision_directives=process_revision_directives,
        **current_app.extensions['migrate'].configure_args,
    )
Run Code Online (Sandbox Code Playgroud)

只需删除或注释process_revision_directives=process_revision_directives,然后添加compare_type=True即可。

像这样:

with connectable.connect() as connection:
    context.configure(
        connection=connection,
        target_metadata=target_metadata,
        # process_revision_directives=process_revision_directives,
        **current_app.extensions['migrate'].configure_args,
        compare_type=True
    )
Run Code Online (Sandbox Code Playgroud)

  • 但你能解释一下这些变化的目的是什么吗 (2认同)