japs
japs

Reputation: 1416

using flask-migration with flask-appbuilder

I have a flask-appbuilder (FAB) project and I would like to use flask-migrate to handle db migrations. However FAB creates the db on its own beforehand, so that flask-migrate cannot compute the migrations

I'm aware of this example and of this issue on FAB's repository, however I wasn't able to use them to solve the problem.

This is a minimal app to show the problem.

# app.py
from flask import Flask
from flask_appbuilder import AppBuilder, SQLA
from flask_migrate import Migrate
import os
from flask_appbuilder import Model
from sqlalchemy import Column, Integer


class Config():
    basedir = os.path.abspath(os.path.dirname(__file__))
    SQLALCHEMY_DATABASE_URI = \
        'sqlite:///' + os.path.join(basedir, 'app.db')
    SQLALCHEMY_TRACK_MODIFICATIONS = False


db = SQLA()
migrate = Migrate()
appbuilder = AppBuilder()


def create_app(config_class=Config):
    app = Flask(__name__)
    app.config.from_object(config_class)
    db.init_app(app)
    migrate.init_app(app, db)

    with app.app_context():
        appbuilder.init_app(app, db.session)
        appbuilder.post_init()

    return app


class MyTable(Model):
    __tablename__ = "my_table"

    id = Column(Integer, primary_key=True)
    mycol = Column(Integer)


if __name__ == "__main__":
    app = create_app()
    app.run()

It can be tested in a virtual environment with the following requirements.txt:

flask-appbuilder==3.1.0
SQLAlchemy==1.3.24
flask-migrate

By issuing

export FLASK_APP=app.py
flask db init
flask db migrate

the output reads INFO [alembic.env] No changes in schema detected, so no migration. However the db has been created.

Note: crossposting from my issue on FAB's repo

Upvotes: 1

Views: 1136

Answers (2)

Kinjal Dixit
Kinjal Dixit

Reputation: 7945

The key is to drop all the tables (the FAB generated tables and alembic_version) before you run flask db upgrade for the first time.

Here is a detailed explanation.

From your projects views.py, find the line

db.create_all()

and comment it out.

install flask-migrate

go to __init__.py add in the imports

from flask_migrate import Migrate

add after db = SQLA(app)

migrate = Migrate(app, db)

The setup is done.

Now only one time in the project to initialise the migrations:

flask db init

This will initialise the migrations.

Now do

flask db migrate

This will create the alembic_version table.

If you do flask db upgrade now, it will lock up. For one time and one time only, drop all the tables in the database. You may want to back up the data so you can restore it later.

flask db upgrade

This will create all the tables, the FAB tables and the models. Now you may want to restore the data.

From here on you can do the migration workflow in the usual manner. Every time you change things in the models.py, do:

flask db migrate
flask db upgrade

Don't drop the tables now.

Upvotes: 0

Lenin
Lenin

Reputation: 430

This solved the problem for me.

$ flask db stamp head # Set current revision in the database to be head
$ flask db migrate
$ flask db upgrade

Upvotes: 0

Related Questions