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()
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)
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 = '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.
Most helpful comment
If anyone comes across this, the solution was to ensure the alembic_versions table was deleted.
or simply delete all the data using DROP ALL