Flask-migrate and changing column type

谁说胖子不能爱 提交于 2019-11-30 15:07:55

问题


I am trying to learn some Flask and I am using Flask-Migrate 1.6.0

So I made a model which looks like this

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)

I have then changed it to the exact same thing except for this line :

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

When I run my

manager.py db migrate

command it doesn't detect the change in the column type. And I have read up on it and I know it should pick it up when I change my env.py and add the compare_type=True variable. But I did this to no avail, the method looks like this right now

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

Ok so my questions are:

Did I do something wrong in changing the env.py file?

If I didn't and it still doesn't pick up on it how do I exactly manually make the next migration revision? Because the revisions in my migrate folder have names like below and stuff in it like this

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

I guess I could just copy one, make up a name .. but would the next one that is picked up by flask migrate recognize it? So yeah.. what is the correct way of handling it without too much iffy hacking?


回答1:


Alembic does not recognize things like column type changes when auto-generating revisions by default. When making these more granular changes, you will need to hand-modify the migration to include these changes

e.g., in your migration file

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

For details on the operations, see the operation reference

You can turn on detection of type changes by modifying your env.py and alembic.ini, as seen here




回答2:


Just need to add compare_type=True in the Migrate constructor

from flask_migrate import Migrate
migrate = Migrate(compare_type=True)

app = Flask(__name__)
migrate.init_app(app)



回答3:


By default, Flask-migrate doesn't track the changes when type of column is changed. One of many ways to achieve this is to set

compare_type=True

Under env.py. e.g. -

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



回答4:


Tha flask-migrate didn't detect the Column changes most of the time. If you delete the size field then flask-migrate will detect the change. Then run

manager.py db migrate

Then add size filed

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




回答5:


I have created a script for an automated way to add the compare_type=true in Flask, feel free to used and improve it.

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

Cheers,



来源:https://stackoverflow.com/questions/33944436/flask-migrate-and-changing-column-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!