Search code examples
pythonsqlalchemyflask-sqlalchemyflask-security

AttributeError: type object 'User' has no attribute 'query'


I have a large database built and populated with sqlalchemy (the original - not flask-SQLAlachemy). I would like to add flask-security to the site, and I realize it relies on flask-SQLAlachemy (instead of the original), but it is my understanding (just started trying to learn more about it) that flask-SQLAlchemy can work with the original. Entering users into the database seems to work. When I navigate to the restricted page, it prompts me to login (as it should). When entering the correct email address and password, I get the error AttributeError: type object 'User' has no attribute 'query', and since the traceback of the error doesn't reference any of my code, I'm not sure how to resolve it.

Thinking this may have been a sqlalchemy to flask-SQLAlchemy conversion issue, I feel like I have tried everything short of creating a new database. I haven't found anything in the flask-security or flask-SQLAlchemy documentation to help resolve this issue. Anyone have an idea on how to resolve this?

Here is my code:

testing.py

from flask import Flask, render_template
from sqlalchemy import create_engine, asc, and_, or_, func, desc
from sqlalchemy.orm import sessionmaker
import database_setup
from database_setup import Base, User, Role
from flask_sqlalchemy import SQLAlchemy
from flask_security import Security, SQLAlchemyUserDatastore, UserMixin, RoleMixin, login_required

application.config['SECRET_KEY'] = 'super-secret'

# Setup Flask-Security
user_datastore = SQLAlchemyUserDatastore(database_setup, User, Role)
security = Security(application, user_datastore)

engine = create_engine('sqlite:///landtohuntalpha.db')
Base.metadata.bind = engine

DBSession = sessionmaker(bind=engine)
session = DBSession()

@application.route('/user/add/', methods = ['GET','POST'])
def addUser():
if request.method == 'POST':
    submission = User(
        email = request.form['email'],
        password = request.form['password'],
    )
    session.add(submission)
    session.commit()
    return redirect(url_for('completedUser'))
else:
    return render_template('addUser.html')

@application.route('/restricted_page/')
@login_required
def restrictedPage():
    return render_template('restricted_page.html')

database_setup.py

import os
import sys
from sqlalchemy import Column, ForeignKey, Integer, String, DateTime, Boolean, Float, Date, Table
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import relationship
from sqlalchemy import create_engine
from flask_security import Security, SQLAlchemyUserDatastore, UserMixin, RoleMixin, login_required

Base = declarative_base()

roles_users = Table('roles_users', Base.metadata, Column('user_id', Integer, ForeignKey('user.id')), Column('role_id', Integer, ForeignKey('role.id')))

class Role(Base, RoleMixin):
    __tablename__ = 'role'
    id = Column(Integer, primary_key=True)
    name = Column(String(80), unique=True)
    description = Column(String(255))

class User(Base, UserMixin):
    __tablename__ = 'user'

    id = Column(Integer, primary_key=True)
    email = Column(String(250), nullable=False)
    password = Column(String(30))
    last_login_at = Column(DateTime)
    active = Column(Boolean)
    confirmed_at = Column(DateTime)
    current_login_at = Column(DateTime)
    last_login_ip = Column(String(45))
    current_login_ip = Column(String(45))
    login_count = Column(Integer)

Traceback Error

File "C:\Python34\lib\site-packages\flask\app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
File "C:\Python34\lib\site-packages\flask\app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
File "C:\Python34\lib\site-packages\flask\app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
File "C:\Python34\lib\site-packages\flask\_compat.py", line 33, in reraise
    raise value
File "C:\Python34\lib\site-packages\flask\app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
File "C:\Python34\lib\site-packages\flask\app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
File "C:\Python34\lib\site-packages\flask\app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
File "C:\Python34\lib\site-packages\flask\_compat.py", line 33, in reraise
    raise value
File "C:\Python34\lib\site-packages\flask\app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
File "C:\Python34\lib\site-packages\flask\app.py", line 1461, in dispatch_request
    return self.view_functions[rule.endpoint](**req.view_args)
File "C:\Python34\lib\site-packages\flask_security\decorators.py", line 205, in wrapper
    return f(*args, **kwargs)
File "C:\Python34\lib\site-packages\flask_security\views.py", line 75, in login
    if form.validate_on_submit():
File "C:\Python34\lib\site-packages\flask_wtf\form.py", line 166, in validate_on_submit
    return self.is_submitted() and self.validate()
File "C:\Python34\lib\site-packages\flask_security\forms.py", line 230, in validate
    self.user = _datastore.get_user(self.email.data)
File "C:\Python34\lib\site-packages\flask_security\datastore.py", line 191, in get_user
    rv = self.user_model.query.filter(query).first()
AttributeError: type object 'User' has no attribute 'query'

Solution

  • your User class is inheriting from UserMixin (from flask-login) which doesn't have a query attribute. can't fully explain the differences between our projects but here is my basic setup:

    init.py:

    from flask import Flask, render_template, session
    from flask.ext.sqlalchemy import SQLAlchemy
    import flask.ext.login as FL
    
    
    # define the main app object
    app = Flask(__name__)
    app.config.from_object('config')
    app.secret_key = 'super secret string'
    
    login_manager = FL.LoginManager()
    login_manager.init_app(app)
    login_manager.login_view = "/"
    
    # create the database object
    db = SQLAlchemy(app)
    

    then in models.py (make sure you import db) make User class inherit from db.Model:

    from flasker import db
    import datetime
    from flask.ext.login import UserMixin
    
    class User(db.Model):
        id = db.Column(db.Integer,primary_key=True)
        email = db.Column(db.Unicode(128))
        name = db.Column(db.Unicode(128))
        password = db.Column(db.Unicode(1024))
        authenticated = db.Column(db.Boolean, default=False)
        posts = db.relationship('Post')
        #-----login requirements-----
        def is_active(self):
        #all users are active
            return True 
    
        def get_id(self):
            # returns the user e-mail. not sure who calls this
            return self.email
    
        def is_authenticated(self):
            return self.authenticated
    
        def is_anonymous(self):
            # False as we do not support annonymity
            return False
    
        #constructor
        def __init__(self, name=None, email=None, password=None):
            self.name = name
            self.email = email
            self.password = password
            self.authenticated = True