我是Python和Flask的新手。
我按照本教程http://douglasstarnes.com/index.php/2015/05/27/easy-authentication-with-flask-login/进行了注册和登录页面的修改,并在注册时对密码进行了哈希处理,并在登录时根据哈希验证密码。
初始密码注册哈希工作正常,但是验证存储在数据库中的哈希密码与通过登录表单以纯文本格式给出的密码不会。
我收到的错误是针对/ login页面上的以下行,原因如下:
if user.count() == 1 and check_password_hash(user.password, password) == True:
AttributeError: 'BaseQuery' object has no attribute 'password'
我无法理解为什么我收到此错误。用户从数据库中成功查询,并且用户在密码列中有密码。
我使用的查询和从密码列返回数据的方法与文档http://flask-sqlalchemy.pocoo.org/2.1/queries/#querying-records中包含的内容类似
这是我的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')
有谁知道为什么我无法访问用户的密码列,或者实际上是任何列?我已经在数据库,ID,用户名和密码中尝试了所有3个。
答案 0 :(得分:14)
@login_manager.user_loader
def user_loader(user_id):
user = User.query.filter_by(id=user_id).first()
if user:
return user
return None
应用.first()
执行查询,而不是存储Query对象
它只返回第一个结果。
.all()
返回所有
编辑:
或者您可以使用user = User.query.get(user_id)
,假设user_id
被定义为PK
在您的登录功能中,它应该是
user = User.query.filter_by(username=username).first()
if user and check_password_hash(user.password, password) == True:
login_user(user)
现在,用户引用了一个真实的User对象,而不是存储的查询。您无法从查询对象
访问用户对象属性(密码)答案 1 :(得分:0)
不要在 SQLQLCHAMY ORM 查询之后错过 .first() 或 .all()。
这总是导致此类错误的原因。