db.create_all() not creating tables in Flask-SQLAlchemy

Question:

I am trying to create a database table for a user class model using Flask-SQLAclchemy and Postgres.

My model class.

from app import db
class User(db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(70), index=True, nullable=False)
    email = db.Column(db.String(70), index=True, unique=True, nullable=False)
    password = db.Column(db.String(128))

My app initialisation.

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
app = Flask(__name__)
app.config.from_object('app.instance.config.DevelopmentConfig')
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://postgres:RandomPass@localhost/BrightEventDb'
SQLALCHEMY_TRACK_MODIFICATIONS = True
db = SQLAlchemy(app)

The following info is logged.

2018-01-06 11:53:09,978 INFO sqlalchemy.engine.base.Engine select version()
2018-01-06 11:53:09,979 INFO sqlalchemy.engine.base.Engine {}
2018-01-06 11:53:09,982 INFO sqlalchemy.engine.base.Engine select current_schema()
2018-01-06 11:53:09,982 INFO sqlalchemy.engine.base.Engine {}
2018-01-06 11:53:09,984 INFO sqlalchemy.engine.base.Engine SELECT CAST('test plain returns' AS VARCHAR(60)) AS anon_1
2018-01-06 11:53:09,985 INFO sqlalchemy.engine.base.Engine {}
2018-01-06 11:53:09,986 INFO sqlalchemy.engine.base.Engine SELECT CAST('test unicode returns' AS VARCHAR(60)) AS anon_1
2018-01-06 11:53:09,987 INFO sqlalchemy.engine.base.Engine {}
2018-01-06 11:53:09,990 INFO sqlalchemy.engine.base.Engine show standard_conforming_strings
2018-01-06 11:53:09,991 INFO sqlalchemy.engine.base.Engine {}
Asked By: Felix Wambiri

||

Answers:

As someone in the comments mentioned you are not importing your model into your app initialisation module. You could do that as follows

from models import User

Answered By: Zahir J

If you were following the flask quick start minimal application, the command worked by default since the User class was in the same place as the db instance. In your case, however, you will have to import the User class as mentioned in the comments from models import User into your app initialization

Answered By: E_K

As per previous comments, besides importing the db sqlalchemy object, you have to import manually your model like so

(venv) $ py -m flask shell
>>> from app import db
>>> from app.models import User
>>> db.create_all()

it’s not that bad for small app with couple models to import, but it will be really tedious when it comes to work with medium / large app with many blueprints each one has its own models, so you have to import all of them manually so you can imagine the amount of typing code in the shell without talking about errors (typos, import modules errors ..), the solution is to use Shell Context to load automatically all objects:

from app import app, db
from app.models import User, Post, Category

@app.shell_context_processor
def make_shell_context():
    return {'db': db, 'User': User, 'Post': Post, 'Category': Category }

now in your shell you can manipulate all objects without any hassle

(venv) $ py -m flask shell
>>> db
<SQLAlchemy engine=sqlite:///data-dev.sqlite>
>>> User
<class 'app.models.User'>
>>> Post
<class 'app.models.Post'>
>>> db.create_all()
Answered By: cizario

Decativate the virtual environment and activate again.

db.create_all()
db.session.commit()
Answered By: Aashish Kumar