Sqlalchemy 使用Alchemy在Alembic自动生成迁移中未检测到任何变化

Sqlalchemy 使用Alchemy在Alembic自动生成迁移中未检测到任何变化,sqlalchemy,flask,database-migration,flask-sqlalchemy,alembic,Sqlalchemy,Flask,Database Migration,Flask Sqlalchemy,Alembic,我很难让Alembic使用db.Model(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['SQL

我很难让Alembic使用
db.Model
(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()
...
这种方法适用于
drop_all()
create_all()
(例如,在为单元测试重新创建测试数据库时),但在这种情况下,它似乎没有效果。自动生成的版本脚本总是有空的升级和降级方法,例如

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

有人在用阿勒姆比克炼金术吗?知道我哪里出错了吗

多谢

试试alembic

我昨天试过了。除了
drop
操作之外,它对我来说工作正常。它们在sqlite()上不起作用

我使用它的方式。 首先,我使用了
python manage.py migrate revision--autogenerate
在sqlite db中创建空表。 它会产生这样的迁移

def upgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.create_table('users_user',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('name', sa.String(length=50), nullable=True),
    sa.Column('email', sa.String(length=120), nullable=True),
    sa.Column('password', sa.String(length=20), nullable=True),
    sa.Column('role', sa.SmallInteger(), nullable=True),
    sa.Column('status', sa.SmallInteger(), nullable=True),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('email'),
    sa.UniqueConstraint('name')
)
### end Alembic commands ###

def downgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('users_user')
    ### end Alembic commands ###
然后-
python manage.py迁移升级头

然后我向用户模型添加了一个新的列
test=db.column(db.String(20))
,并运行了这个命令
python manage.py migrate revision--autogenerate-m'testfieldat users'

这就产生了这种迁移:

def upgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.add_column('users_user', sa.Column('test', sa.String(length=20), nullable=True))
    ### end Alembic commands ###


def downgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.drop_column('users_user', 'test')
    ### end Alembic commands ###

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

Alembic文档摘录:

默认情况下,自动生成将检测:

  • 表的添加、删除
  • 列的添加、删除
  • 更改列上的可空状态
自动生成可以选择性地检测:

  • 更改列类型。如果在
    EnvironmentContext.configure()
    上设置
    compare\u type=True
    ,则会发生这种情况。该特性在大多数情况下工作良好,但在默认情况下处于关闭状态,因此可以首先在目标模式上对其进行测试。它也可以通过在这里传递一个callable来定制;有关详细信息,请参阅函数的文档
  • 更改服务器默认值。如果在
    EnvironmentContext.configure()
    上设置
    compare\u server\u default=True,则会发生这种情况。此功能适用于简单情况,但不能始终产生准确的结果。Postgresql后端实际上会对数据库调用“检测到的”和“元数据”值以确定等价性。默认情况下,该功能处于关闭状态,因此可以首先在目标架构上对其进行测试。与类型比较一样,它也可以通过传递一个callable来定制;有关详细信息,请参阅函数的文档
自动生成无法检测到:

  • 表名的更改。这些表将作为两个不同表的添加/删除,应该手动编辑为名称更改
  • 列名的更改。与表名更改一样,这些更改被检测为列添加/删除对,这与名称更改完全不同
  • 在不直接支持
    Enum
    的后端上生成特殊的SQLAlchemy类型,例如
    Enum
    ——这是因为非支持数据库中此类类型的表示,即
    CHAR+CHECK
    约束,可以是任何类型的
    CHAR+CHECK
    。对于SQLAlchemy来说,确定这实际上是一个
    ENUM
    只是一个猜测,这通常是一个坏主意。要在此处实现您自己的“猜测”功能,请使用
    sqlalchemy.events.DDLEvents.column\u reflect()
    事件来更改为某些列传递的sqlalchemy类型,可能还有
    sqlalchemy.events.DDLEvents.after\u parent\u attach()
    来拦截不需要的
    检查
    约束
Autogenerate当前无法检测,但最终将检测到:

  • 独立约束的添加和删除,如
    检查
    唯一
    外键
    ——这些尚未实现。现在,您将获得新表中的约束,用于“降级”到以前存在的表的PK和FK约束,以及使用SQLAlchemy“schema”类型生成的
    检查
    约束
    布尔
    枚举
  • 索引添加、删除-尚未实施
  • 序列添加、删除-尚未实施

更新:Alembic 0.7.x版本支持上一个列表中的某些项。

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

我也面临这个问题,并用这种方法解决了这个问题:

打开
migrations/env.py
文件,在
def run_migrations_online()
函数上查看
上下文。在
Alembic 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,
    )
只需删除或注释
process\u revision\u directives=process\u revision\u directives
,然后在上面添加
compare\u 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
    )

这可能是一个愚蠢的建议,但我也有类似的问题。我所有的env文件都指向了正确的位置,但我仍然无法生成这个新表。我使用了命令序列“alembic revision-m'comment'”和“alembic升级头”,得到了“空”版本文件

最后,在删除所有迁移文件、销毁docker映像、恢复迁移文件、重新尝试上面的cli命令序列之后,在手动编写迁移代码之前,我尝试了“ale”
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
    )