Flask-Migrate: Can't detect models.py schema

Hi, miguelgrinberg: I’m trying out this library along with instruction, in the following style of code i have put all the code in one file:

from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.script import Manager
from flask.ext.migrate import Migrate, MigrateCommand

app = Flask(__name__, static_path='/static')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db'
db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)

class User(db.Model):
        #code here

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

And when i type “python app.py db init” and “python app.py db migrate”, the migration script is generated just fine.

Then i delete .db file and “migrations” folder and want to try this in the following setting: i put all the database model definition in the file “models.py” which is at the same level with “app.py”

from app import db, app

class User(db.Model):
        #code here

And in “app.py”

from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.script import Manager
from flask.ext.migrate import Migrate, MigrateCommand

import models

app = Flask(__name__, static_path='/static')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db'
db = SQLAlchemy(app)
migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)


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

And after initialization and “python app.py db migrate”, the migration script shows:

# revision identifiers, used by Alembic.
revision = ******
down_revision = None

from alembic import op
import sqlalchemy as sa


def upgrade():
    ### commands auto generated by Alembic - please adjust! ###
    pass
    ### end Alembic commands ###


def downgrade():
    ### commands auto generated by Alembic - please adjust! ###
    pass
    ### end Alembic commands ###

Which means flask-migrate doesn’t detect database model definition in this type of code layout. I’m not sure why this is the case, definitely somewhere has been messed up, but i’m not sure where is it.

Thanks in advance

About this issue

  • Original URL
  • State: closed
  • Created 9 years ago
  • Comments: 17 (6 by maintainers)

Most upvoted comments

Hi @jeffjzx. The problem is that models.py uses the db instance, so you need to import it after db has been created. Try this:

from flask.ext.sqlalchemy import SQLAlchemy
from flask.ext.script import Manager
from flask.ext.migrate import Migrate, MigrateCommand

app = Flask(__name__, static_path='/static')
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///data.db'

db = SQLAlchemy(app)
import models     # <--- move this anywhere after db is instantiated

migrate = Migrate(app, db)
manager = Manager(app)
manager.add_command('db', MigrateCommand)


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

I’m surprised you are not getting a circular reference issue with your code.

I used this to recursively import all models.

# manager.py

import importlib
import os

from app import manager

MODELS_DIRECTORY = "models"
EXCLUDE_FILES = ["__init__.py"]

def import_models():
    for dir_path, dir_names, file_names in os.walk(MODELS_DIRECTORY):
        for file_name in file_names:
            if file_name.endswith("py") and not file_name in EXCLUDE_FILES:
                file_path_wo_ext, _ = os.path.splitext((os.path.join(dir_path, file_name)))
                module_name = file_path_wo_ext.replace(os.sep, ".")
                importlib.import_module(module_name)


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

In my case I was not using flask-sqlalchemy, just plain alchemy. (My models were subclass of Base). Solve it by using flask-alchemy (db.Model)

@miguelgrinberg, no, the table was empty. I managed to solve it now, though, through some restructuring of my code.

The problem in my case was that the initialization code was located in the package’s __init__.py. Due to app.config.from_object(...), which was loading a module located inside of the package, the code in __init__.py would be executed twice. The first time, all models were correctly identified and could be found in the metadata, however the second time they were not.

@jbaiter: any chance you have a database that already has the tables in it? If that’s the case, then Alembic is not going to find any difference between your models and the database. Try dropping all the tables in your database.