Flask引用flask-login引发登入错误请大神解惑,flaskflask-login,自己在学习Flask时,


自己在学习Flask时,使用flask-login遇到问题。

程序是一个很简单的登录鉴权的程序,如果用户输入用户名和密码正确,则可以查看到首页,否则回到登录页面让用户输入用户名和密码。

目前遇到的问题是,输入错误的用户名和密码不可登录(正常),但输入正确的用户名和密码后,程序报错。

开启Flask调试模式,报错信息如下:

builtins.TypeError TypeError: 'NoneType' object is not callable

Traceback (most recent call last) File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask/app.py",
line 1836, in call return self.wsgi_app(environ, start_response)
File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask/app.py",
line 1820, in wsgi_app response =
self.make_response(self.handle_exception(e)) File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask/app.py",
line 1403, in handle_exception reraise(exc_type, exc_value, tb) File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask/_compat.py",
line 33, in reraise raise value File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask/app.py",
line 1817, in wsgi_app response = self.full_dispatch_request() File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask/app.py",
line 1477, in full_dispatch_request rv = self.handle_user_exception(e)
File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask/app.py",
line 1381, in handle_user_exception reraise(exc_type, exc_value, tb)
File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask/_compat.py",
line 33, in reraise raise value File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask/app.py",
line 1475, in full_dispatch_request rv = self.dispatch_request() File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask/app.py",
line 1461, in dispatch_request return
self.view_functionsrule.endpoint File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask_login.py",
line 756, in decorated_view elif not current_user.is_authenticated():
File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/werkzeug/local.py",
line 338, in getattr return getattr(self._get_current_object(),
name) File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/werkzeug/local.py",
line 297, in _get_current_object return self.__local() File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask_login.py",
line 46, in current_user = LocalProxy(lambda: _get_user())
File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask_login.py",
line 794, in _get_user current_app.login_manager._load_user() File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask_login.py",
line 363, in _load_user return self.reload_user() File
"/Users/duzhipeng/project/xianpi/venv/lib/python3.4/site-packages/flask_login.py",
line 325, in reload_user user = self.user_callback(user_id) TypeError:
'NoneType' object is not callable The debugger caught an exception in
your WSGI application. You can now look at the traceback which led to
the error. To switch between the interactive traceback and the
plaintext one, you can click on the "Traceback" headline. From the
text traceback you can also create a paste of it. For code execution
mouse-over the frame you want to debug and click on the console icon
on the right side.

You can execute arbitrary Python code in the stack frames and there
are some extra helpers available for introspection:

dump() shows all variables in the frame dump(obj) dumps all that's
known about the object

主程序就两个文件,源码分别如下:
run.py

# -*- coding: utf-8 -*-import osfrom flask import Flask, render_template, redirect, url_for, flashfrom flask.ext.sqlalchemy import SQLAlchemyfrom flask_wtf import Formfrom wtforms import StringField, PasswordField, SubmitFieldfrom wtforms.validators import DataRequiredfrom flask.ext.login import LoginManager, login_required, login_userbasedir = os.path.abspath(os.path.dirname(__file__))app = Flask(__name__)app.config['SECRET_KEY'] = 'stong key'app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////' + os.path.join(basedir, 'date.sqlite')app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = Truedb = SQLAlchemy(app)login_manager = LoginManager(app)login_manager.session_protection = 'strong'login_manager.login_view = 'login'class LoginForm(Form):    username = StringField('用户名', validators=[DataRequired()])    password = PasswordField('密码', validators=[DataRequired()])    submit = SubmitField()@app.route('/')@login_requireddef index():    return 'hello'@app.route('/login', methods=['GET', 'POST'])def login():    from models import Admin    form = LoginForm()    if form.validate_on_submit():        user = Admin.query.filter_by(username=form.username.data).first()        if user is not None and user.verify_password(form.password.data):            login_user(user)            return redirect(url_for('index'))        flash('用户名或密码错误')    return render_template('login.html', form=form)if __name__ == '__main__':    app.run(debug=True)

models.py

# -*- coding: utf-8 -*-from werkzeug.security import generate_password_hash, check_password_hashfrom flask.ext.login import UserMixinfrom run import db, login_managerclass Admin(UserMixin, db.Model):    __tablename__ = 'admin'    id = db.Column(db.Integer, primary_key=True)    username = db.Column(db.String(64), unique=True)    password_hash = db.Column(db.String(128), unique=False)    @property    def password(self):        raise AttributeError('不能直接获取明文密码!')    @password.setter    def password(self, password):        self.password_hash = generate_password_hash(password)    def verify_password(self, password):        return check_password_hash(self.password_hash, password)    def __repr__(self):        return "<Admin '{:s}>".format(self.username)@login_manager.user_loaderdef load_user(user_id):    return Admin.query.get(int(user_id))if __name__ == '__main__':    db.create_all()

我自己觉得是login_manager.user_loader 回调有问题,user_id从哪里来的也弄不明白。

自己GG和看了例子大概3个小时了,还是无解,因此特来请大神解惑。

谢谢!

自己知道错误在哪里了。

@login_manager.user_loaderdef load_user(user_id):    return Admin.query.get(int(user_id))

@login_manager.user_loader 写到models里了,导致没有被调用生效。改到run里就可以了。不过这和书上的不同,例子也不同。这点我还得研究研究。

编橙之家文章,

评论关闭