SQLAlchemy create_all() does not create tables SQLAlchemy create_all() does not create tables postgresql postgresql

SQLAlchemy create_all() does not create tables


You should put your model class before create_all() call, like this:

from flask import Flaskfrom flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://login:pass@localhost/flask_app'db = SQLAlchemy(app)class User(db.Model):    id = db.Column(db.Integer, primary_key=True)    username = db.Column(db.String(80), unique=True)    email = db.Column(db.String(120), unique=True)    def __init__(self, username, email):        self.username = username        self.email = email    def __repr__(self):        return '<User %r>' % self.usernamedb.create_all()db.session.commit()admin = User('admin', 'admin@example.com')guest = User('guest', 'guest@example.com')db.session.add(admin)db.session.add(guest)db.session.commit()users = User.query.all()print users

If your models are declared in a separate module, import them before calling create_all().

Say, the User model is in a file called models.py,

from flask import Flaskfrom flask_sqlalchemy import SQLAlchemyapp = Flask(__name__)app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql+psycopg2://login:pass@localhost/flask_app'db = SQLAlchemy(app)# See important note belowfrom models import Userdb.create_all()db.session.commit()admin = User('admin', 'admin@example.com')guest = User('guest', 'guest@example.com')db.session.add(admin)db.session.add(guest)db.session.commit()users = User.query.all()print users

Important note: It is important that you import your models after initializing the db object since, in your models.py _you also need to import the db object from this module.


This is probably not the main reason why the create_all() method call doesn't work for people, but for me, the cobbled together instructions from various tutorials have it such that I was creating my db in a request context, meaning I have something like:

# lib/db.pyfrom flask import g, current_appfrom flask_sqlalchemy import SQLAlchemydef get_db():  if 'db' not in g:    g.db = SQLAlchemy(current_app)  return g.db

I also have a separate cli command that also does the create_all:

# tasks/db.pyfrom lib.db import get_db@current_app.cli.command('init-db')def init_db():  db = get_db()  db.create_all()

I also am using a application factory.

When the cli command is run, a new app context is used, which means a new db is used. Furthermore, in this world, an import model in the init_db method does not do anything, because it may be that your model file was already loaded(and associated with a separate db).

The fix that I came around to was to make sure that the db was a single global reference:

# lib/db.pyfrom flask import g, current_appfrom flask_sqlalchemy import SQLAlchemydb = Nonedef get_db():  global db  if not db:    db = SQLAlchemy(current_app)  return db

I have not dug deep enough into flask, sqlalchemy, or flask-sqlalchemy to understand if this means that requests to the db from multiple threads are safe, but if you're reading this you're likely stuck in the baby stages of understanding these concepts too.


If someone is having issues with creating tables by using files dedicated to each model, be aware of running the "create_all" function from a file different from the one where that function is declared.So, if the filesystem is like this:

Root  --app.py     <-- file from which app will be run--models----user.py      <-- file with "User" model----order.py    <-- file with "Order" model----database.py <-- file with database and "create_all" function declaration

Be careful about calling the "create_all" function from app.py.

This concept is explained better by the answer to this thread posted by @SuperShoot