Flask-Migrate not creating tables

Created on 2 Jul 2018  ·  19Comments  ·  Source: miguelgrinberg/Flask-Migrate

python manage.py db init && python manage.py db migrate && python manage.py db upgrade

All commands run without error messages yet no tables were created. Here are the relevant files:

project/__init__.py

from flask import Flask
from flask_sqlalchemy import SQLAlchemy

db = SQLAlchemy()

def create_app():
    app = Flask(__name__)
    app.config.from_object(os.environ['APP_SETTINGS'])
    db.init_app(app)
    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 Migrate, MigrateCommand
from project.models import *
from flask_sqlalchemy import SQLAlchemy
from run import app


db = SQLAlchemy(app)

migrate = Migrate(app, db)
manager = Manager(app)

manager.add_command('db', MigrateCommand)

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

Most helpful comment

If anyone comes across this, the solution was to ensure the alembic_versions table was deleted.

$ psql database
psql (10.4)
Type "help" for help.

database=# DROP TABLE alembic_versions;

or simply delete all the data using DROP ALL

All 19 comments

Please add the output of all those commands that you are running.

@miguelgrinberg based on your stackoverflow answer, I integrated the correct app factory pattern but yet it is still not working:

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

manage.py

from flask_script import Manager
from flask_migrate import MigrateCommand
from project import create_app


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

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

Running the following still doesn't detect my models and then create tables:

> python manage.py db migrate
INFO  [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO  [alembic.runtime.migration] Will assume transactional DDL.
>

@joekendal are your project/models.py using the correct db instance? i.e. from project import db? rather than some other instance?

@wgwz Yes, I have this in my project/models.py

from project import db, login_manager
...
class User(db.Model):

i think there is a circular import. i think the circular import happens when you do “from project import create_app” in manage.py.

one solution could be to instantiate the manager in the project/init.py nearly the same as you have already done with db and migrate.

this way does not depend on importing create_app into manager.py, which i believe causes a db instance to be created separately from the db instance that is being used in the models. which im guessing means that the MigrateCommand sees a db instance that does not have models attached to it.

but im taking a bit of a wild guess here, and could be totally wrong!

@wgwz
project/__init__.py

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

db = SQLAlchemy()
migrate = Migrate()
manager = Manager()

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

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

    return app

```shell

export FLASK_APP=run.py
flask db migrate

```python
Traceback (most recent call last):
  File "$HOME/Project/venv/bin/flask", line 11, in <module>
    sys.exit(main())
  File "$HOME/Project/venv/lib/python3.6/site-packages/flask/cli.py", line 894, in main
    cli.main(args=args, prog_name=name)
  File "$HOME/Project/venv/lib/python3.6/site-packages/flask/cli.py", line 557, in main
    return super(FlaskGroup, self).main(*args, **kwargs)
  File "$HOME/Project/venv/lib/python3.6/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "$HOME/Project/venv/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "$HOME/Project/venv/lib/python3.6/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "$HOME/Project/venv/lib/python3.6/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "$HOME/Project/venv/lib/python3.6/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "$HOME/Project/venv/lib/python3.6/site-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "$HOME/Project/venv/lib/python3.6/site-packages/flask/cli.py", line 411, in decorator
    with __ctx.ensure_object(ScriptInfo).load_app().app_context():
  File "$HOME/Project/venv/lib/python3.6/site-packages/flask/cli.py", line 372, in load_app
    app = locate_app(self, import_name, name)
  File "$HOME/Project/venv/lib/python3.6/site-packages/flask/cli.py", line 235, in locate_app
    __import__(module_name)
  File "$HOME/Project/run.py", line 3, in <module>
    app = create_app()
  File "$HOME/Project/__init__.py", line 30, in create_app
    manager.init_app(app)
AttributeError: 'Manager' object has no attribute 'init_app'

go back to what you had and try moving the instantiation for db and migrate into a separate module. that may also resolve it but again i’m not entirely sure. can share the code?

it seems you are mixing two patterns here a bit, using export FLASK_APP and flask_script. idk, i’m glad to help more if you can share a link to the code. at this point there are too many variables that i cant see for me to accurately diagnose. read this carefully: https://flask-migrate.readthedocs.io/en/latest/

iirc based on what ive seen in your code you can just remove the manager object for now from project/init and for good measure imprts related to it. and then just try flask db init and flask db upgrade. assuming you use the FLASK_APP pattern. cheers and good luck!

Hi, I've made a repo I can share with you on GitHub with the same setup and problem

just gotta import the models:

```(venv) $ git diff
diff --git a/project/__init__.py b/project/__init__.py
index 4949ace..f3f09af 100644
--- a/project/__init__.py
+++ b/project/__init__.py
@@ -12,6 +12,7 @@ def create_app():
app = Flask(__name__)
app.config.from_object(Config)

  • from project import models
    db.init_app(app)
    migrate.init_app(app, db)
i did actually test it too:

(venv) $ flask db init
(venv) $ flask db migrate
(venv) $ cat migrations/versions/2a8a093c14f0_.py
"""empty message

Revision ID: 2a8a093c14f0
Revises:
Create Date: 2018-07-03 00:49:56.548064

"""
from alembic import op
import sqlalchemy as sa

revision identifiers, used by Alembic.

revision = '2a8a093c14f0'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('first_name', sa.String(length=50), nullable=True),
sa.PrimaryKeyConstraint('id')
)
op.drop_table('quotes')
op.drop_table('users')
op.drop_table('resources')
# ### end Alembic commands ###

def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('resources',
sa.Column('id', sa.INTEGER(), server_default=sa.text("nextval('resources_id_seq'::regclass)"), autoincrement=True, nullable=False),
sa.Column('link', sa.VARCHAR(), autoincrement=False, nullable=False),
sa.PrimaryKeyConstraint('id', name='resources_pkey'),
postgresql_ignore_search_path=False
)
op.create_table('users',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('name', sa.VARCHAR(), autoincrement=False, nullable=False),
sa.PrimaryKeyConstraint('id', name='users_pkey')
)
op.create_table('quotes',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('text', sa.VARCHAR(), autoincrement=False, nullable=False),
sa.Column('resource_id', sa.INTEGER(), autoincrement=False, nullable=True),
sa.ForeignKeyConstraint(['resource_id'], ['resources.id'], name='quotes_resource_id_fkey'),
sa.PrimaryKeyConstraint('id', name='quotes_pkey')
)
op.drop_table('user')
# ### end Alembic commands ###
```
in @miguelgrinberg's project i believe he does it this way: https://github.com/miguelgrinberg/flasky/blob/9bcab0e17504629b4bfe7ca557f1fc44d920f767/app/main/__init__.py when the blueprint is registered the model is imported.

@wgwz I'm really confused because I've tried that before, I've tried that now and it still doesn't work for me

diff --git a/project/__init__.py b/project/__init__.py
index 4949ace..f3f09af 100644
--- a/project/__init__.py
+++ b/project/__init__.py
@@ -12,6 +12,7 @@ def create_app():
     app = Flask(__name__)
     app.config.from_object(Config)

+    from project import models
     db.init_app(app)
     migrate.init_app(app, db)

```shell
(venv) flask db migrate
INFO [alembic.runtime.migration] Context impl PostgresqlImpl.
INFO [alembic.runtime.migration] Will assume transactional DDL.
(venv) ls migrations/versions/
(venv)

If it was an issue with postgresql, then I have no idea why I'm able to create the tables with:
```python
(venv) python
>>> from project import create_app, db
>>> app = create_app()
>>> app.app_context().push()
>>> db.init_app(app)
>>> db.create_all()
>>> db.session.commit()

the only other thing i changed was removing the if name equals main block in the run.py file but i dont think that matters.

@wgwz Wow very strange.. Was able to get it to work on a different box (centos) but not on this (mac)... Why would that be the case though since we're using virtual environments here ? How can I try to debug this?

could also have been that something was wrong in the migrations folder.

If anyone comes across this, the solution was to ensure the alembic_versions table was deleted.

$ psql database
psql (10.4)
Type "help" for help.

database=# DROP TABLE alembic_versions;

or simply delete all the data using DROP ALL

@joekendal i had the exact same issue as you, and dropping alembic_versions solved it.
Can someone explain why that was the case? i still don't get it

I had this issue. It turned out that I had
net_total = db.column(db.Integer)
instead of
net_total = db.Column(db.Integer)

in my table definition. Once that was fixed, the table was detected and created.

@valinsky because Alembic relies on some metadata so if you mess around with your database without using Alembic then it will be confused as to what happened when you want to use it again.

Was this page helpful?
0 / 5 - 0 ratings