6

I have the following project structure:

project/__init__.py

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

db = SQLAlchemy()
migrate = Migrate()

def create_app():
    app = Flask(__name__)
    app.config.from_object(os.environ['APP_SETTINGS'])

    db.init_app(app)
    migrate.init_app(app, db)

    return app

run.py

from project import create_app
app = create_app()

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

manage.py

from flask_script import Manager
from flask_migrate import MigrateCommand
from project.models import *
from project import create_app


manager = Manager(create_app)
manager.add_command('db', MigrateCommand)

if __name__ == '__main__':
    manager.run()

Yet when I run the following commands, Flask-Migrate is not detecting any tables to be added.

python manage.py db init

Which outputs:

Creating directory $HOME/Project/migrations ... done
Creating directory $HOME/Project/migrations/versions ... done
Generating $HOME/Project/migrations/script.py.mako ... done
Generating $HOME/Project/migrations/env.py ... done
Generating $HOME/Project/migrations/README ... done
Generating $HOME/Project/migrations/alembic.ini ... done
Please edit configuration/connection/logging settings in
'$HOME/Project/migrations/alembic.ini' before proceeding.

and

python manage.py db migrate

Which only outputs:

INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.

Why is Flask-Migrate with Alembic not detecting the Models and therefore creating the tables? Here's what I've tried:

  • Deleting the database, starting from nothing
  • Creating a custom db class inside the manage.py file, doesn't detect that
  • Googling every answer to this problem, found lots of similar questions but none of their solutions worked for me.

EDIT:

Here is an example of the models.py file

from flask import current_app
from project import db
from flask_login import UserMixin

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(50))
Joe
  • 175
  • 2
  • 11
  • what do your models look like? – wgwz Jul 03 '18 at 00:40
  • @wgwz my models.py file is too big to share the whole thing but i've included only a relevant example. It's not an issue with my models as I can use db.create_all() in a shell successfully – Joe Jul 03 '18 at 00:46
  • ah ha. i think its likely because you created the db object in multiple places. you’ll be better off using the approach to instantiating flask extensions project/__init__.py than in the manage.py. – wgwz Jul 03 '18 at 00:50
  • id guess you are overriding the db instance in your manage.py – wgwz Jul 03 '18 at 00:51
  • it is important to show the models.py bc the import statements could explain why its not working – wgwz Jul 03 '18 at 00:52
  • you could just paste a segment of it – wgwz Jul 03 '18 at 00:52
  • Even when I import it though from \_\_init\_\_.py it is still an empty SQLAlchemy object since it is added to the app object with db.init_app(app) in the create_app() function. Is there a way I can access the db object that is assigned to the app with my setup? – Joe Jul 03 '18 at 00:54
  • of course “from project import db” that will give you the db instance which you attached to app instance – wgwz Jul 03 '18 at 00:56
  • I've tried that though and if i print the db object I get: since it gets attached to the app inside the create_app() function and not outside of it. – Joe Jul 03 '18 at 00:58
  • also you should be setting up the migrate extension the same way as db – wgwz Jul 03 '18 at 00:58
  • I've updated the question to show you what I've tried with the import and as the db is not attached to an app outside of the create_app(), it has a __repr__ of – Joe Jul 03 '18 at 01:01
  • @wgwz I am not sure what you mean by setting up the migrate extension the same way as db – Joe Jul 03 '18 at 01:01
  • 1. pass Manager create_app instead of app 2. look up flask migrate init_app. 3. pretty sure you have a circular import but dont have the time to prove it right now! best of luck – wgwz Jul 03 '18 at 01:08
  • If you want to add the import models, will accept the answer as complete thanks – Joe Jul 03 '18 at 07:57

2 Answers2

10

The solution was to import the models in the __init__.py file like so:

def create_app():
    app = Flask(__name__)
    app.config.from_object(os.environ['APP_SETTINGS'])

    from project import models

    db.init_app(app)
    migrate.init_app(app, db)

    return app
Joe
  • 175
  • 2
  • 11
0

I had the same issue. The solution is pretty same as @joe's

In routes file

from models import User

api_user = Namespace('user', description='user related operations')

In project/__init__.py

def create_app():
    app = Flask(__name__)
    app.config.from_object(os.environ['APP_SETTINGS'])

    from project import models

    db.init_app(app)
    migrate.init_app(app, db)

    blueprint = Blueprint('api', __name__, url_prefix=url_prefix)
    api = Api(blueprint, doc='/documentation')  # ,doc=False

    app.register_blueprint(blueprint)
    api.add_namespace(api_user)

return app

when adding api_user namespace in create_app flask_migrate detected models