sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table

Viewed 78984

I am fresh to flask and was trying to build a blog on my own, and I ran into an issue with SQLite operation error. I have researched similar problem on Github and Stackoverflow but none of the typical typo or error in old questions happens to me. It would be appreciated and really great if anyone can help me because this problem is like killing me and already cost me two days, I feel really bad.

In the code I have defined the table name which is "users_table" and run "db.create_all()" at the beginning to create the table, but the error keeps occurring with "no such table user_table" each time when a commit happens for updating user info.

This is how I test the SQLite operation:

(under /project) python3 manage.py shell
>>> u = User(email='foo@bar.com', username='foobar', password='player')
>>> db.create_all()
>>> db.session.add(u)
>>> db.session.commit()  # with following error message
Traceback (most recent call last):
  File "C:\...\Python\Python36-32\lib\site-packages\sqlalchemy\engine\base.py", line 1182, in _execute_context
  context)
  File "C:\...\Python\Python36-32\lib\site-packages\sqlalchemy\engine\default.py", line 470, in do_execute
  cursor.execute(statement, parameters)
sqlite3.OperationalError: no such table: users_table
...
...
  sqlalchemy.exc.OperationalError: (sqlite3.OperationalError) no such table: users_table

I have minimized the code into following four sections, which can reoccur the error message:

/project/app/__init__.py:

from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from config import config

db = SQLAlchemy()

def create_app(config_name):
    app = Flask(__name__)
    app.config.from_object(config[config_name])
    config[config_name].init_app(app)
    db.init_app(app)
    return app

/project/app/models.py:

import os
from flask_sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash
from flask import Flask

basedir = os.path.abspath(os.path.dirname(__file__))

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
db = SQLAlchemy(app)


class User(db.Model):
    __tablename__ = 'users_table'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(64), unique=True, index=True)
    username = db.Column(db.String(64), unique=True, index=True)
    password_hash = db.Column(db.String(128))

    def __repr__(self):
        return '<User %r>' % self.username

    @property
    def password(self):
        raise AttributeError('Password is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

project/config.py:

import os
basedir = os.path.abspath(os.path.dirname(\__file__))

class Config:
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'fhuaioe7832of67^&*T#oy93'
    SQLALCHEMY_COMMIT_ON_TEARDOWN = True

    @staticmethod
    def init_app(app):
        pass

class DevelopmentConfig(Config):
    DEBUG = True
    SQLALCHEMY_DATABASE_URI = 'sqlite:///' + os.path.join(basedir, 'data.sqlite')

config = {
    'development': DevelopmentConfig,
    'default': DevelopmentConfig,
}

project/manage.py:

import os
from app import create_app, db
from app.models import User
from flask_script import Manager, Shell

app = create_app(os.getenv('FLASK_CONFIG') or 'default')
manager = Manager(app)

def make_shell_context():
    return dict(app=app, db=db, User=User)

manager.add_command("shell", Shell(make_context=make_shell_context))


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

Very simple solution: in the app.py or main.py you can just add these lines of code for fixing this issue:

@app.before_first_request
def create_tables():
    db.create_all()

In your case, require to add following code into __init__.py:

from models import User, Role

@app.shell_context_processor
def make_shell_context():
    return dict(db=db, User=User, Role=Role)

then you do your previous works, it's all work.

Related