我无法让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()
(例如,在为单元测试重新创建测试数据库时),但在这种情况下似乎没有实现。自动生成的版本脚本始终具有空的升级和降级方法,例如,
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和Flask-SQLAlchemy?知道我哪里错了吗?
非常感谢!
答案 0 :(得分:34)
Alembic无法自动检测表格或列重命名。默认情况下,它也不会查找列类型更改,但可以为此启用compare_type
选项。
摘录自Alembic文件:
默认情况下,Autogenerate将检测:
自动生成可以选择检测:
compare_type=True
上设置EnvironmentContext.configure()
,则会发生这种情况。该功能在大多数情况下运行良好,但默认情况下处于关闭状态,因此可以首先在目标模式上对其进行测试。它也可以通过传递一个可调用来定制;有关详细信息,请参阅功能文档。compare_server_default=True
上设置EnvironmentContext.configure()
,则会发生这种情况。此功能适用于简单的情况,但不能始终产生准确的结果。 Postgresql后端实际上将针对数据库调用“检测到的”和“元数据”值以确定等效性。默认情况下,该功能处于关闭状态,因此可以首先在目标模式上对其进行测试。像类型比较一样,它也可以通过传递一个可调用来定制;有关详细信息,请参阅功能文档。自动生成无法检测到:
Enum
在后端生成时直接不支持ENUM
- 这是因为在非支持数据库中表示此类型,即{{1}约束,可以是任何类型的CHAR+CHECK
。对于SQLAlchemy来确定这实际上只是一个CHAR+CHECK
只是猜测,这通常是一个坏主意。要在此处实现您自己的“猜测”功能,请使用ENUM
事件来更改为某些列传递的SQLAlchemy类型,并可能sqlalchemy.events.DDLEvents.column_reflect()
拦截不需要的sqlalchemy.events.DDLEvents.after_parent_attach()
约束。目前无法自动生成,但最终会检测到:
CHECK
,CHECK
,UNIQUE
- 这些尚未实施。现在,您将在新表中获得约束,PK和FK约束用于“降级”到先前存在的表,以及使用SQLAlchemy“模式”类型生成的FOREIGN KEY
约束类型CHECK
,{{ 1}}。更新:Alembic 0.7.x版本支持最后一个列表中的一些项目。
答案 1 :(得分:4)
我的错误是尝试创建我的初始迁移,db已经处于最终状态,认为它会注意到它没有现有版本并且基于模型。我得到了空版本,直到我删除了数据库中的所有表,然后它工作正常。
答案 2 :(得分:1)
我也遇到了这个问题,并使用这种方式来解决这个问题:
打开migrations/env.py
文件,然后在def run_migrations_online()
函数上查看context.configure
,在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_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
)
答案 3 :(得分:0)
尝试flask-alembic https://github.com/tobiasandtobias/flask-alembic
我昨天试过了。除drop
操作外,它对我来说很好。它们不适用于sqlite(https://bitbucket.org/zzzeek/alembic/issue/21/column-renames-not-supported-on-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 migrate upgrade head
然后我向User模型添加了一个新列test = db.Column(db.String(20))
并运行了此命令python manage.py migrate revision --autogenerate -m 'test field at 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 ###
答案 4 :(得分:0)
如果您发现您需要的功能在alembic中不受支持。在这种情况下
删除表格(或列),然后迁移
添加表格(或列),然后再次迁移
这也适用于枚举类型更改
答案 5 :(得分:0)
这可能是一个愚蠢的建议,但是我遇到了类似的问题。我所有的env文件都指向正确的位置,等等,但是我仍然无法生成这个新表。我使用命令序列“ alembic版本-m'注释”,然后使用“ alembic升级头”,得到了“空”版本文件。
最后,在删除所有迁移文件,销毁docker映像,恢复迁移文件,重新尝试上述cli命令序列之后,并且在手动手动编码迁移之前,我尝试了“高级修订--autogenerate”,找到并创建了表的迁移。
这可能是由于我之前采取的所有其他步骤。如果不是很有帮助,我深表歉意。