using flask-migrate with flask-script and application factory
Asked Answered
F

1

9

I'm building flask application and decided to try application factory approach this time, but got into trouble with flask-migrate and can't figure out simple solution.

Please note that I want to pass config location as an option to the script

manage.py:

manager = Manager(create_app)
manager.add_option("-c", "--config", dest="config_module", required=False)

then i need to create migrate instance and add command to the manager:

with manager.app.app_context():
    migrate = Migrate(current_app, db)
    manager.add_command('db', MigrateCommand)

but app instance is not created yet, so it fails

I know I can pass config in environment variable and create application before creating manager instance, but how to do it using manager options?

Frigidaire answered 26/4, 2015 at 2:6 Comment(0)
A
23

When you use a --config option you have to use an application factory function as you know, as this function gets the config as an argument and that allows you to create the app with the right configuration.

Since you have an app factory, you have to use the deferred initialization for all your extensions. You instantiate your extensions without passing any arguments, and then in your app factory function after you create the application, you call init_app on all your extensions, passing the app and db now that you have them.

The MigrateCommand is completely separate from this, you can add that to the Manager without having app and db instances created.

Example:

manage.py:

from app import create_app
from flask_migrate import MigrateCommand, Manager

manager = Manager(create_app)
manager.add_option("-c", "--config", dest="config_module", required=False)
manager.add_command('db', MigrateCommand)

app.py (or however your app factory module is called)

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_migrate import Migrate

db = SQLAlchemy()
migrate = Migrate()

def create_app(config):
    app = Flask(__name__)
    # apply configuration
    # ...

    # initialize extensions
    db.init_app(app)
    migrate.init_app(app, db)

    return app
Airframe answered 26/4, 2015 at 19:20 Comment(5)
Are you sure your example works, Miguel? I'm getting empty migrations here.Curren
Do you get valid migrations if you use Alembic directly? My guess is that your problem is unrelated to the Flask-Script setup.Airframe
@ItaloMaia I know this is old, but I am also getting empty migrations. How did you solved the problem?Turboprop
Empty migrations here as well...Barcus
@FirdausIndradhirmaya try importing the model inside the create_app func, worked for meMcgaha

© 2022 - 2024 — McMap. All rights reserved.