understand setting up database using sqlalchamy and avoid errorAttributeError: type object 'User' has no attribute 'query' in flask app

Question:

I am a beginner writing a todo app in flask and in writing database application, at least I have never setup db for any production app myself.

I have written this code (models.py) that uses sqlalchemy ORM to define table model.

from sqlalchemy import create_engine, Column, Integer, String, Boolean
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship

from datetime import datetime
from .extensions import db
from .config import app


# define base for declarative ORM
Base = declarative_base()

class User(Base):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    username = Column(String, unique=True)
    password = Column(String)

    def __repr__(self):
        return '<User {}>'.format(self.username)


class Todo(Base):
    __tablename__ = 'todos'

    id = Column(db.Integer, primary_key=True)
    title = Column(db.String(255))
    description = Column(db.Text)
    created_at = Column(db.DateTime, default=datetime.utcnow)
    completed = Column(Boolean)
    user_id = Column(db.Integer, db.ForeignKey('user.id'))
    user = relationship('User', back_populates='todos')

    def __repr__(self):
        return '<Todo {}>'.format(self.id)


User.todos = relationship('Todo', order_by=Todo.id, back_populates='user')

# create database engine
engine = create_engine(app.config['SQLALCHEMY_DATABASE_URI'])

# create all tables
Base.metadata.create_all(engine)

extensions.py

from .config import app
from flask_sqlalchemy import SQLAlchemy


db = SQLAlchemy(app)

config.py

from flask import Flask
from datetime import timedelta


app = Flask(__name__)

finally the start.py

from todo_app.extensions import db
from flask import Flask

from todo_app.endpoint import todo_bp, auth_bp


def create_app(config_file='settings.cfg'):
    app = Flask(__name__, instance_relative_config=True)
    app.config.from_pyfile(config_file)
    db.init_app(app)
    app.register_blueprint(auth_bp)
    app.register_blueprint(todo_bp)
    return app


if __name__ == '__main__':
    app = create_app()
    app.run()

but when I run the command python start.py

I get the following error:

$ python start.py 

* Running on http://127.0.0.1:5000 (Press CTRL+C to quit)
[2022-12-29 20:01:57,004] ERROR in app: Exception on / [GET]
Traceback (most recent call last):
  File "/home/ciasto/Dev/crud_app/crud_app_env/lib/python3.10/site-packages/flask/app.py", line 2077, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/ciasto/Dev/crud_app/crud_app_env/lib/python3.10/site-packages/flask/app.py", line 1525, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/ciasto/Dev/crud_app/crud_app_env/lib/python3.10/site-packages/flask_restplus/api.py", line 584, in error_router
    return original_handler(e)
  File "/home/ciasto/Dev/crud_app/crud_app_env/lib/python3.10/site-packages/flask/app.py", line 1523, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/ciasto/Dev/crud_app/crud_app_env/lib/python3.10/site-packages/flask/app.py", line 1509, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "/home/ciasto/Dev/crud_app/src/todo_app/endpoint.py", line 105, in index
    user = User.query.filter_by(id=user_id).first()
AttributeError: type object 'User' has no attribute 'query'

This is the endpoint.py

# todo index endpoint
@todo_bp.route('/')
def index():
    # get the logged in user
    user_id = session.get('user_id')
    user = User.query.filter_by(id=user_id).first()

    # get the todo items for the user
    todos = user.todos

    return render_template('index.html', todos=todos)
Asked By: Ciasto piekarz

||

Answers:

Your code is mixing idioms from the base SQLAlchemy package and Flask-SQLAlchemy. When using Flask-SQLAlchemy, your model classes should inherit from db.Model, not Base (db.Model extends Base further, and adds some Flask-SQLAlchemy features, like the query attribute).

In fact, the majority of common SQLAlchemy features that you might want to use are exposed through the db namespace in Flask-SQLAlchemy – you should rarely need to import SQLAlchemy itself.

See also this Q&A for the reverse of this problem.

Answered By: snakecharmerb