web-dev-qa-db-ja.com

フラスコ-sqlalchemy-ユーザークエリ「BaseQuery」オブジェクトには属性「パスワード」がありません

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つすべてを試しました。

7
rossd
@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_idがPKとして定義されていると仮定して、user = User.query.get(user_id)を使用できます。

ログイン機能では、

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

これで、ユーザーは、保存されたクエリではなく、実際のUserオブジェクトを参照します。クエリオブジェクトからユーザーオブジェクト属性(パスワード)にアクセスできない

21
Busturdust