Flask-Login: где должен быть определен обратный вызов user_loader?

Я новичок в программировании на Python, но сразу же начал экспериментировать с flask. У меня проблемы с расширением flask-login. Здесь я создаю простое приложение - блог. Этот блог будет использоваться только одним человеком.

Я не могу понять, почему декоратор user_loader не работает, который определен в models.py. Я получаю исключение: объект NoneType приложения не может быть вызван. Моя структура приложения такая

.
|-- app
|   |-- admin
|   |   |-- __init__.py
|   |   |-- static
|   |   |-- templates
|   |   `-- views.py
|   |-- config.py
|   |-- __init__.py
|   |-- main
|   |   |-- __init__.py
|   |   |-- static
|   |   |-- templates
|   |   `-- views.py
|   `-- models.py
`-- launch.py

app. init

from flask import Flask
from main import main
from admin import admin
from flask.ext.script import Manager
from .config import config
from flask_debugtoolbar import DebugToolbarExtension
from flask.ext.sqlalchemy import SQLAlchemy
from sqlalchemy import Column
from flask_bootstrap import Bootstrap
from flask.ext.moment import Moment
from flask.ext.login import LoginManager


app_myblog=Flask(__name__)
app_myblog.debug=True
app_myblog.config.from_object(config)
app_myblog.register_blueprint(main)
app_myblog.register_blueprint(admin,url_prefix="/admin"
toolbar=DebugToolbarExtension(app_myblog)
manager=Manager(app_myblog)
db=SQLAlchemy(app_myblog)
Bootstrap(app_myblog)
moment=Moment(app_myblog)

login_manager=LoginManager()
login_manager.init_app(app_myblog)
login_manager.session_protection='strong'
login_manager.login_view='admin.login'

В app.models я определил класс User, который не загружает пользователей из базы данных. Фактически он просто загружает пользователя из конфигурации. В том же файле я также определил обратный вызов user_loader

class User(UserMixin):
    def __init__(self):
        self.id='1'
        self.name=app_myblog.config['USERNAME']
        self.password=app_myblog.config['PASSWORD']

    def get_id(self):
        return unicode(id)

@login_manager.user_loader
def load_user(userid):
    u=User()
    if u.get_id()==userid:
        return u
    else:
        return None

admin. init

from flask import Blueprint

admin=Blueprint('admin',__name__,template_folder='templates',static_folder='static')
from . import views

admin.views

from flask import render_template,request,redirect,url_for
from . import admin
from flask.ext.login import login_required,login_user
from flask_wtf.form import Form
from wtforms import StringField,PasswordField,SubmitField
from ..models import User



class LoginForm(Form):
    username=StringField('Username')
    password=PasswordField('Password')
    submit=SubmitField('Login')


@admin.route('/')
@login_required
def index():
    return render_template('admin_home.html')


@admin.route('/login',methods=['GET','POST'])
def login():
    form=LoginForm()
    if form.validate_on_submit():
        login_user(User())
        nextx = request.args.get('next')
        return redirect(nextx or url_for('admin.index'))
    return render_template('admin_login.html',form=form)

Всякий раз, когда я запускаю маршруты, которые имеют login_required, я получаю ошибку TypeError: объект «NoneType» не вызывается. Вот трассировка.

Traceback (most recent call last):
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1836, in __call__
    return self.wsgi_app(environ, start_response)
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1820, in wsgi_app
    response = self.make_response(self.handle_exception(e))
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1403, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1817, in wsgi_app
    response = self.full_dispatch_request()
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1477, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1381, in handle_user_exception
    reraise(exc_type, exc_value, tb)
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask/app.py", line 1475, in full_dispatch_request
    rv = self.dispatch_request()
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask_debugtoolbar/__init__.py", line 125, in dispatch_request
    return view_func(**req.view_args)
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask_login.py", line 756, in decorated_view
    elif not current_user.is_authenticated():
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/werkzeug/local.py", line 338, in __getattr__
    return getattr(self._get_current_object(), name)
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/werkzeug/local.py", line 297, in _get_current_object
    return self.__local()
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask_login.py", line 46, in <lambda>
    current_user = LocalProxy(lambda: _get_user())
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask_login.py", line 794, in _get_user
    current_app.login_manager._load_user()
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask_login.py", line 363, in _load_user
    return self.reload_user()
  File "/home/shivam/Workspaces/PythonWorkSpace/MyBlog/venv/lib/python2.7/site-packages/flask_login.py", line 325, in reload_user
    user = self.user_callback(user_id)
TypeError: 'NoneType' object is not callable

person user274823    schedule 24.06.2015    source источник
comment
У меня такой же вопрос. Ни один из них не отвечает на вопрос и не говорит об этом в документации.   -  person Mote Zart    schedule 31.12.2019


Ответы (2)


Изменить: я создал минимальный пример вашего кода, и разница заключалась в том, что я удалил функцию get_id(self) (+ некоторые дополнительные библиотеки, которые не нужны), потому что это часть класса UserMixin, который вы наследуете.

Вы уверены, что ваша форма проверяется? Можете ли вы описать, как вы это тестируете шаг за шагом? Я имею в виду, «перейти к login.html» -> «ввести учетные данные» -> и т. Д.

Убедитесь, какой вызов вызывает сбой, это redirect внутри вашей функции входа в систему?

person Zyber    schedule 25.06.2015
comment
Это не решает проблемы. Обратный вызов user_loader даже не выполняется. - person user274823; 25.06.2015
comment
Логин работает нормально. Перенаправление тоже работает нормально. Но когда открывается перенаправленная страница, приложение вылетает. Я думаю, что не находит функции обратного вызова. - person user274823; 25.06.2015

Вы должны определить метод там же, где вы создаете экземпляр менеджера входа в систему.

аля

login = LoginManager
@login.user_loader
def load_user(id/email):
    #your logic here

Или импортируйте свой экземпляр loginmanager из своего модуля и определите его в своих представлениях.

person Callam Delaney    schedule 27.06.2017