使用 Flask-SQLAlchemy 在 Alembic 自动生成迁移中未检测到任何变化 [英] No changes detected in Alembic autogeneration of migrations with Flask-SQLAlchemy

查看:57
本文介绍了使用 Flask-SQLAlchemy 在 Alembic 自动生成迁移中未检测到任何变化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm having trouble getting Alembic to autogenerate candidate migrations from changes to classes using db.Model (Flask-SQLAlchemy) instead of Base.

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

I've modified env.py to create my Flask app, import all relevant models, initialize the database, and then run migrations:

...
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()
...

这种方法适用于 drop_all()create_all()(例如,当为单元测试重新创建测试数据库时),但它似乎在这个案例.自动生成的版本脚本总是有空的升级和降级方法,e.g.,

This approach works fine for drop_all(), create_all() (for example, when recreating a test db for unit testing), but it seems to fall flat in this case. The auto generated version scripts always have empty upgrade and downgrade methods, e.g.,

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 ###

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

My changes have included renaming columns, changing column definitions, etc., not just changes to indices and foreign keys.

有人在 Flask-SQLAlchemy 中使用 Alembic 吗?知道我哪里出错了吗?

Is anyone out there using Alembic with Flask-SQLAlchemy? Any idea where I'm going wrong?

非常感谢!

推荐答案

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

Alembic cannot automatically detect table or column renames. By default it will not look for column type changes either, but the compare_type option can be enabled for this.

摘自 Alembic 文档:

Excerpt from the Alembic documentation:

自动生成将默认检测:

  • 表的添加、删除.
  • 添加、删除列.
  • 更改列的可为空状态.

Autogenerate 可以选择检测:

Autogenerate can optionally detect:

  • 更改列类型.如果您在 EnvironmentContext.configure() 上设置 compare_type=True,就会发生这种情况.该功能在大多数情况下运行良好,但默认情况下处于关闭状态,以便可以首先在目标模式上进行测试.也可以通过在此处传递可调用对象来自定义;有关详细信息,请参阅函数的文档.
  • 更改服务器默认设置.如果您在 EnvironmentContext.configure() 上设置 compare_server_default=True,就会发生这种情况.此功能适用于简单的情况,但不能始终产生准确的结果.Postgresql 后端实际上会针对数据库调用检测到"和元数据"值以确定等效性.该功能默认处于关闭状态,因此可以先在目标架构上进行测试.和类型比较一样,也可以通过传递一个callable来自定义;有关详细信息,请参阅函数的文档.
  • Change of column type. This will occur if you set compare_type=True on EnvironmentContext.configure(). The feature works well in most cases, but is off by default so that it can be tested on the target schema first. It can also be customized by passing a callable here; see the function’s documentation for details.
  • Change of server default. This will occur if you set compare_server_default=True on EnvironmentContext.configure(). This feature works well for simple cases but cannot always produce accurate results. The Postgresql backend will actually invoke the "detected" and "metadata" values against the database to determine equivalence. The feature is off by default so that it can be tested on the target schema first. Like type comparison, it can also be customized by passing a callable; see the function’s documentation for details.

自动生成无法检测:

  • 表名的变化.这些将作为两个不同表的添加/删除而出现,并且应该手动编辑为名称更改.
  • 列名的变化.与表名更改一样,这些被检测为列添加/删除对,这与名称更改完全不同.
  • 特殊的 SQLAlchemy 类型,例如 Enum 在不直接支持 ENUM 的后端上生成 - 这是因为在不支持的数据库中这种类型的表示,即CHAR+CHECK 约束,可以是任何类型的CHAR+CHECK.对于 SQLAlchemy 确定这实际上是一个 ENUM 只是一个猜测,这通常是一个坏主意.要在此处实现您自己的猜测"功能,请使用 sqlalchemy.events.DDLEvents.column_reflect() 事件来更改为某些列传递的 SQLAlchemy 类型,可能还有 sqlalchemy.events.DDLEvents.after_parent_attach() 拦截不需要的 CHECK 约束.
  • Changes of table name. These will come out as an add/drop of two different tables, and should be hand-edited into a name change instead.
  • Changes of column name. Like table name changes, these are detected as a column add/drop pair, which is not at all the same as a name change.
  • Special SQLAlchemy types such as Enum when generated on a backend which doesn’t support ENUM directly - this because the representation of such a type in the non-supporting database, i.e. a CHAR+CHECK constraint, could be any kind of CHAR+CHECK. For SQLAlchemy to determine that this is actually an ENUM would only be a guess, something that’s generally a bad idea. To implement your own "guessing" function here, use the sqlalchemy.events.DDLEvents.column_reflect() event to alter the SQLAlchemy type passed for certain columns and possibly sqlalchemy.events.DDLEvents.after_parent_attach() to intercept unwanted CHECK constraints.

Autogenerate 目前不能,但最终会检测到:

Autogenerate can’t currently, but will eventually detect:

  • 独立约束的添加、删除,例如 CHECKUNIQUEFOREIGN KEY - 这些尚未实现.现在,您将获得新表中的约束、用于降级"到先前存在的表的 PK 和 FK 约束,以及使用 SQLAlchemy模式"类型生成的 CHECK 约束Boolean, 枚举.
  • 索引添加、删除 - 尚未实施.
  • 序列添加、删除 - 尚未实施.
  • Free-standing constraint additions, removals, like CHECK, UNIQUE, FOREIGN KEY - these aren’t yet implemented. Right now you’ll get constraints within new tables, PK and FK constraints for the "downgrade" to a previously existing table, and the CHECK constraints generated with a SQLAlchemy "schema" types Boolean, Enum.
  • Index additions, removals - not yet implemented.
  • Sequence additions, removals - not yet implemented.

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

UPDATE: some of the items in this last list are supported in the Alembic 0.7.x releases.

这篇关于使用 Flask-SQLAlchemy 在 Alembic 自动生成迁移中未检测到任何变化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆