5
votes

I want to use flask_login to manager user login but some error like this:

Exception: No user_loader has been installed for this LoginManager. Add one with the 'LoginManager.user_loader' decorator.

this is my models.py (PS:I use Flask peewee to build my models)

from peewee import *
from playhouse.fields import ManyToManyField
from .__init__ import login_manager
from flask_login import UserMixin, AnonymousUserMixin

db = SqliteDatabase('adminSystem.db')

class BaseModel(Model):
    class Meta:
        database = db

class User(UserMixin, BaseModel):
    name = CharField()
    email = CharField()
    is_admin = BooleanField()
    username = CharField()
    passwd_hash = CharField()
    teacher = ForeignKeyField('self', related_name='students', null=True)

    #def is_authenticated(self):
    #    return True

    #def is_active(self):
    #    return True

    #def is_anonymous(self):
    #    return False

    #def get_id(self):
    #    try:
    #        return unicode(self.id)
    #   except NameError:
    #        return str(self.id)

class Homework(BaseModel):
    owner = ForeignKeyField(User, related_name='homeworks', null=True)
    pub_datetime = DateTimeField()
    connect = TextField()
    homework_id =CharField()
    file_url = CharField()

class Score(BaseModel):
    homework_id = CharField()
    stu_id = CharField()
    grade = IntegerField()
    file_url = CharField()

class AnonymousUser(AnonymousUserMixin):
    def can(self, permissions):
        return False

    def is_administrator(self):
        return False

@login_manager.user_loader
def load_user(userid):
    try:
        #: Flask Peewee used here to return the user object
        return User.get(User.id==userid)
    except User.DoesNotExist:
        return None

and this is some part of my view.py

from flask import render_template, url_for, redirect, request, g
from . import auth
from werkzeug.security import generate_password_hash, check_password_hash
from ..models import db, User, Homework, Score
from flask_login import login_user, logout_user, login_required, current_user

@auth.before_app_request
def before_request():
    g.user = current_user

@auth.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        if request.form['role'] == 'teacher':
            user = User.get(User.username == request.form['username'])
            if check_password_hash(user.passwd_hash, request.form['password']):
                login_user(user)
                return redirect(url_for('main.post'))
            return render_template('login.html')
        elif request.form['role'] == 'student':
            user = User.get(User.username == request.form['username'])
            if check_password_hash(user.passwd_hash, request.form['password']):
                login_user(user)
                return redirect(url_for('main.show'))
            return render_template('login.html')
    return render_template('login.html')

and there is a picture that I had try

enter image description here

5
when I put @login_manager.user_loader under login_manager.init_app(app) it worksShawn Lu

5 Answers

7
votes

you can place this method

@login_manager.user_loader
def load_user(user_id):
    return None

at after login_manager.init_app(app)

4
votes

According to https://flask-login.readthedocs.io/en/latest/#configuring-your-application

Once the actual application object has been created, you can configure it for login with:

login_manager.init_app(app)

After that, you can register callbacks by using decorators etc. So that the login_manager has the context to process.

1
votes

In my case (following Miguel Grinberg's tutorial, part 6), what was needed was just to restart the server.

0
votes

As @code said, but instead you return None try to return the user data.

Add in yourapp.py this code below the login_manager instance.

@login_manager.user_loader
def load_user(id):
    return User.query.filter_by(user_id=id).first()

After that you can delete the @login_manager decorator and its respect function from your model.py

0
votes

This solved my problem

@login_manager.user_loader

def load_user(username): return get_user(username)