自己在學習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 os
from flask import Flask, render_template, redirect, url_for, flash
from flask.ext.sqlalchemy import SQLAlchemy
from flask_wtf import Form
from wtforms import StringField, PasswordField, SubmitField
from wtforms.validators import DataRequired
from flask.ext.login import LoginManager, login_required, login_user
basedir = 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'] = True
db = 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_required
def 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_hash
from flask.ext.login import UserMixin
from run import db, login_manager
class 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_loader
def 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個小時了,還是無解,因此特來請大神解惑。
謝謝!
新手學習Flask引用flask-login后登入錯誤原因不清
慕尼黑8549860
2019-02-21 09:48:33