【问题标题】:Flask-migrate and changing column type烧瓶迁移和更改列类型
【发布时间】:2016-02-29 21:23:51
【问题描述】:

我正在尝试学习一些 Flask,我正在使用 Flask-Migrate 1.6.0

所以我做了一个看起来像这样的模型

class Download(db.Model):

    __tablename__ = "downloads"

    id = db.Column(db.Integer, autoincrement=True, primary_key=True)
    filename = db.Column(db.String, nullable=False)
    size = db.Column(db.Integer, nullable=False)
    location = db.Column(db.String, nullable=False)
    season = db.Column(db.Integer, nullable=False)
    download_timestamp = db.Column(db.DateTime, nullable=False)

    show_id = db.Column(db.Integer, ForeignKey("shows.id"))

    def __init__(self,filename,size,location,timestamp,season):
        self.filename = filename
        self.size = size
        self.location = location
        self.download_timestamp = timestamp
        self.season = season

    def __repr__(self):
        return '<File {}'.format(self.filename)

然后我将其更改为完全相同的内容,除了这一行:

size = db.Column(db.BigInteger, nullable=False)

当我运行我的

manager.py db migrate

命令它不会检测到列类型的变化。而且我已经阅读了它,我知道当我更改我的 env.py 并添加 compare_type=True 变量时它应该拿起它。但是我这样做没有用,方法现在看起来像这样

def run_migrations_online():
    """Run migrations in 'online' mode.

    In this scenario we need to create an Engine
    and associate a connection with the context.

    """

    # this callback is used to prevent an auto-migration from being generated
    # when there are no changes to the schema
    # reference: http://alembic.readthedocs.org/en/latest/cookbook.html
    def process_revision_directives(context, revision, directives):
        if getattr(config.cmd_opts, 'autogenerate', False):
            script = directives[0]
            if script.upgrade_ops.is_empty():
                directives[:] = []
                logger.info('No changes in schema detected.')

    engine = engine_from_config(config.get_section(config.config_ini_section),
                                prefix='sqlalchemy.',
                                poolclass=pool.NullPool)

    connection = engine.connect()
    context.configure(connection=connection,
                      target_metadata=target_metadata,
                      compare_type=True,
                      process_revision_directives=process_revision_directives,
                      **current_app.extensions['migrate'].configure_args)

    try:
        with context.begin_transaction():
            context.run_migrations()
    finally:
        connection.close()

好的,我的问题是:

我在更改 env.py 文件时做错了吗?

如果我没有并且它仍然没有接受它,我该如何手动进行下一个迁移修订?因为我的 migrate 文件夹中的修订具有如下名称,并且其中的内容如下所示

# revision identifiers, used by Alembic.
revision = '7e9f264b0f'
down_revision = '2e59d536f50'

我想我可以只复制一个,编一个名字.. 但是flask migrate 拾取的下一个会识别它吗?所以是的.. 没有太多可疑的黑客攻击的正确处理方法是什么?

【问题讨论】:

    标签: postgresql python-3.x flask alembic


    【解决方案1】:

    只需要在 Migrate 构造函数中添加compare_type=True

    from flask_migrate import Migrate
    migrate = Migrate(compare_type=True)
    
    app = Flask(__name__)
    migrate.init_app(app)
    

    【讨论】:

    • 这是正确答案。
    • 正确而干净的答案。
    • 这应该是公认的答案。完美运行。
    • Alembic 用户,请参见此处以获取等效信息:alembic.sqlalchemy.org/en/latest/…
    • 这应该是公认的答案。让另一个被接受真是令人困惑。
    【解决方案2】:

    更新:

    正如预期的那样,这个答案现在已经过时了,请查看https://stackoverflow.com/a/52181159/428907 以获得真正的修复!

    原答案:

    默认情况下,自动生成修订时,Alembic 无法识别列类型更改等内容。在进行这些更精细的更改时,您需要手动修改迁移以包含这些更改

    例如,在您的迁移文件中

    from alembic import op
    import sqlalchemy as sa
    def upgrade():
        # ...
        op.alter_column('downloads', 'size', existing_type=sa.Integer(), type_=sa.BigInteger())
    def downgrade():
        # ...
        op.alter_column('downloads', 'size', existing_type=sa.BigInteger(), type_=sa.Integer())
    

    具体操作见the operation reference

    您可以通过修改您的 env.py 和 alembic.ini 来开启对类型更改的检测,如 here 所示

    【讨论】:

    • 提供的链接失效了...操作参考可以在这里找到:alembic.zzzcomputing.com/en/latest/ops.html
    • 如果您必须编写自己的迁移,这很有用,但这不是必需的,最好更改默认行为并初始化 alembic 以检测这些迁移。正确答案如下 - 更改默认行为以检测这些类型的更改。
    • 此链接有助于选择准确的代码来修改 env.py 文件以进行 alembic 迁移:github.com/miguelgrinberg/Flask-Migrate/issues/24
    【解决方案3】:

    我已经创建了一个脚本,用于在 Flask 中自动添加 compare_type=true,请随意使用和改进它。

    make dbinit
    sudo sed -i '75i\                      compare_type=True,' env.py
    make dbmigrate
    make dbupgadre
    

    干杯,

    【讨论】:

      【解决方案4】:

      默认情况下,Flask-migrate 不会在列类型更改时跟踪更改。实现这一目标的众多方法之一是设置

      compare_type=True

      在 env.py 下。例如-

      context.configure(connection=connection,
                            target_metadata=target_metadata,
                            process_revision_directives=process_revision_directives,
                            compare_type=True,
                            **current_app.extensions['migrate'].configure_args)
      

      【讨论】:

      • 我可能做错了什么,但这种方法似乎不适用于 Flask-Migrate 2.5.2。
      【解决方案5】:

      Tha flask-migrate 大部分时间都没有检测到 Column 更改。如果您删除 size 字段,则 flask-migrate 将检测到更改。然后运行

      manager.py db migrate

      然后添加size归档

      size = db.Column(db.BigInteger, nullable=False) 并迁移。

      【讨论】:

      • 好吧,但是在保存数据方面会增加很多麻烦吗?
      猜你喜欢
      • 2016-09-02
      • 1970-01-01
      • 2019-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多