Python flask-sqlalchemy - 用户查询“BaseQuery”对象没有“密码”属性

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34795798/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 15:32:03  来源:igfitidea点击:

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

pythonloginflasksqlalchemyflask-sqlalchemy

提问by rossd

I'm new to Python and Flask.

我是 Python 和 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.

我正在按照本教程http://douglasstarnes.com/index.php/2015/05/27/easy-authentication-with-flask-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:

我收到的错误是针对 /login 页面上的以下行,原因如下:

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

我正在使用的查询和从密码列返回数据的方法与文档http://flask-sqlalchemy.pocoo.org/2.1/queries/#querying-records中包含的类似

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

这是我的 views.py(/login 和错误行在底部)

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.

有谁知道为什么我无法访问用户的密码列,或者实际上任何列?我已经尝试了数据库、ID、用户名和密码中的所有 3 个。

采纳答案by Busturdust

@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.

应用.first()执行查询,而不是存储 Query 对象,它将只返回第一个结果。

.all()returns all

.all()全部返回

edit:

编辑:

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

或者您可以使用user = User.query.get(user_id)假设user_id定义为 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

现在用户引用一个真正的用户对象,而不是存储的查询。您无法从查询对象访问用户对象属性(密码)