Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

flask-sqlalchemy - User Query 'BaseQuery' object has no attribute 'password'

I'm new to Python and Flask.

I'm following this tutorial http://douglasstarnes.com/index.php/2015/05/27/easy-authentication-with-flask-login/ to have registration and login pages and have slightly modified it to hash the passwords on registration and to verify the password against the hash on login.

Initial password registration hashing works, but verifying the hashed password stored in the database against the one given in plain text via a login form does not.

The error I am receiving is against the following line on /login page and for the following reason:

if user.count() == 1 and check_password_hash(user.password, password) == True:

AttributeError: 'BaseQuery' object has no attribute 'password'

I cannot work out why I'm receiving this error. The user gets successfully queried from the database, and the user has it's hashed password within the password column.

The query I'm using and method of returning data from the password column are similar to that included in the documentation http://flask-sqlalchemy.pocoo.org/2.1/queries/#querying-records

This is my views.py (/login and the erroring line are towards the bottom)

from flask import Flask, render_template, request, abort, redirect, url_for, flash
from flask.ext.login import LoginManager, UserMixin, login_user, logout_user, login_required
from flask.ext.sqlalchemy import SQLAlchemy
from werkzeug.security import generate_password_hash, check_password_hash
from app import app
import os

login_manager = LoginManager(app)
login_manager.init_app(app)
login_manager.login_view = 'login'
login_manager.session_protection = "strong"

db = SQLAlchemy(app)

class User(db.Model, UserMixin):
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String)
    password = db.Column(db.String)

@login_manager.user_loader
def user_loader(user_id):
    user = User.query.filter_by(id=user_id)
    if user.count() == 1:
    return user.one()
    return None

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

@app.route('/secret')
@login_required
def secret():
    return render_template('secret.html')

@app.route('/logout')
def logout():
    logout_user()
    return redirect(url_for('index'))

@app.route('/register', methods=['GET', 'POST'])
def register():
    if request.method == 'GET':
    return render_template('register.html')
    elif request.method == 'POST':
    username = request.form['txtUsername']
    password = request.form['txtPassword']
    user = User.query.filter_by(username=username)
    if user.count() == 0:
        hashed_password = generate_password_hash(password)
        user = User(username=username, password=hashed_password)
        db.session.add(user)
        db.session.commit()

        flash('You have registered the username {0}. Please login'.format(username))
        return redirect(url_for('login'))
    else:
        flash('The username {0} is already in use.  Please try a new username.'.format(username))
        return redirect(url_for('register'))
    else:
    abort(405)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'GET':
    return render_template('login.html', next=request.args.get('next'))
    elif request.method == 'POST':
    username = request.form['txtUsername']
    password = request.form['txtPassword']
    user = User.query.filter_by(username=username)
    if user.count() == 1 and check_password_hash(user.password, password) == True:
        login_user(user.one(), remember=True)
        flash('Welcome back {0}'.format(username))
        try:
            next = request.form['next']
            return redirect(next)
        except:
            return redirect(url_for('index'))
    else:
        flash('Invalid login')
        return redirect(url_for('login'))
    else:
    return abort(405)

@app.route('/')
def index():
    return render_template('index.html')

Does anyone know why I cannot access the password column for the user, or in fact any column? I've tried all 3 within the database, ID, username and password.

like image 480
rossd Avatar asked Jan 14 '16 17:01

rossd


People also ask

How do I query a SQL Server database in flask?

To query database we use the query () method of the session object. The query () method returns a flask_sqlalchemy.BaseQuery object which is just an extension of the original sqlalchemy.orm.query.Query object. The flask_sqlalchemy.BaseQuery object represents the SELECT statement that will be used to query the database.

Why do we use flask and SQLAlchemy?

We imported Flask, SQLAlchemy to help our Python application communicate with a database, Bcrypt for password hashing, Migrate for database migrations, and several other methods from Flask-Login for session management.

How do I filter a SELECT query in flask-SQLAlchemy?

For this purpose Flask-SQLAlchemy provides a query attribute on your Model class. When you access it you will get back a new query object over all records. You can then use methods like filter () to filter the records before you fire the select with all () or first (). If you want to go by primary key you can also use get ().

Is it possible to access a user's password from a query?

Now user references a real User object, as opposed to a stored query. you cannot access a User Object attribute (password) from a Query Object Show activity on this post.


1 Answers

@login_manager.user_loader
def user_loader(user_id):
    user = User.query.filter_by(id=user_id).first()
    if user:
        return user
    return None

Applying the .first() executes the query, instead of storing the Query object it will return only the first result.

.all() returns all

edit:

or you could use user = User.query.get(user_id) assuming user_id is defined as PK

In your Login Function it should be

  user = User.query.filter_by(username=username).first()
    if user and check_password_hash(user.password, password) == True:
        login_user(user)

Now user references a real User object, as opposed to a stored query. you cannot access a User Object attribute (password) from a Query Object

like image 161
Busturdust Avatar answered Sep 17 '22 17:09

Busturdust