AttributeError: type object 'User' has no attribute 'query'
Asked Answered
G

4

11

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'
Glider answered 23/7, 2015 at 5:6 Comment(2)
The problem seems to be with setting up DB connection...@MarkEbby
@upaangsaxena I'm not sure what is wrong with the connection. Can you elaborate? ThanksGlider
F
7

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
Fairchild answered 22/1, 2016 at 9:34 Comment(2)
@Mark: This is simply suggesting non-use of the Declarative Base, which is not required, nor recommended, to fix the problem as described. You need to add Base.query = session.query_property() after declaring Base (and also in a session context). Then, the flask-security module will be able to access your User/etc tables using User.query... syntax.Kruse
Note that flasker is now deprecated. Use kit instead.Peppergrass
N
7

Add

Base.query = db_session.query_property()

under

Base = declarative_base()

in

database_setup.py

Ref: https://pythonhosted.org/Flask-Security/quickstart.html#id2

Nuncio answered 2/7, 2020 at 5:44 Comment(0)
S
2

You can try to modify the way you create db Models like this:

class User(db.Model):
    # parms

Generally create Models in this way will be able to let User use query method. Hope it helps.

Suite answered 5/7, 2019 at 3:25 Comment(0)
K
0

In case anyone gets a similar error when using Flask-Admin, check where you add the ModelViews to the admin object.

from flask_admin import Admin
admin = Admin()

Here:

                                               ↓ ↓ ↓ ↓ 
admin.add_view(YourModelView(YourModelClass, db.session))

If it's not a db.session object, you would get a similar error.

Kotto answered 25/6, 2023 at 23:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.