Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AttributeError: module 'flask_login.login_manager' has no attribute 'user_loader' when using Flask login without modal

I have the following code that I am trying to do authentication using Flask:

from flask import Flask
from flask_login import LoginManager, login_manager
from auth.auth import auth_bp
from environments.environments import environments_bp
from migration.migration import migration_bp
from logs.logs import logs_bp

UPLOAD_FOLDER = 'static/uploads'

@login_manager.user_loader
def load_user(user_id):
    # since the user_id is just the primary key of our user table, use it in the query for the user
    return True

def create_app():

    app = Flask(__name__)

    app.register_blueprint(auth_bp, url_prefix='/auth')
    app.register_blueprint(environments_bp, url_prefix='/environments')
    app.register_blueprint(migration_bp, url_prefix='/migration')
    app.register_blueprint(logs_bp, url_prefix='/logs')

    app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
    app.secret_key = b'_5#y2L"F4Q8z\n\xec]/'

    login_manager_copy = LoginManager()
    login_manager_copy.login_view = 'auth.login'
    login_manager_copy.init_app(app)

    return app

I am not using any database and the authentication is just a hardcoded if check as this is for an internal tool for single time usage.

How can fix this error ?

like image 604
Happy Coder Avatar asked Oct 29 '25 03:10

Happy Coder


2 Answers

You are decorating the load_user function before your LoginManager() object is created in your app factory create_app()

For a nicely organized application, you should configure the LoginManager to work with your app inside your app factory as you are trying to do now.

def create_app():
    app = Flask(__name__)
    ...
    login_manager = LoginManager()
    login_manager.init_app(app)
    ...
    return app

Then in your authorization blueprint you access the login_manager in your the app object proxy current_app, and you define your load_user call back function there

from flask import current_app as app
...
...
@app.login_manager.userloader # Here your app is already created and configured with login manager
def load_user(_id):
    #Get your user from the database or where ever you are storing your user information and construct the user object to return
    if user_found:
      return user
    else:
      return None
...
...

Don't forget they you will also need save_user function that you call to save the user (you can choose to save it on a DB or any other place you see fit)on successful login.

Now with every request this callback function will be called and it will reload the user object you saved using the userID stored in the session (cookie for example). If it finds a user with the corresponding ID, it will construct the user object as per you logic in the load_user callback function, and you will have a user proxy called current_user that you can access within the request's context

For example within a GET request you can do

if current_user.age < 19:
  raise Unauthorized("Too young to rent a car")

I strongly recommend reading the Flask-Login documentation thoroughly and it will make it easier to understand the flow.

like image 178
mowienay Avatar answered Oct 30 '25 16:10

mowienay


If you are here after following the digital ocean tutorial. Please follow the following code and you should be good to go.

from flask import Flask,request
from flask_migrate import Migrate
from .routes import auth
from flask import g
from .models.models import db
from flask_babel import Babel
from .settings import config
from flask_login import LoginManager
from .models.models import User
from .settings import config
import json

login_manager = LoginManager()
app = Flask(__name__)

app.config['SECRET_KEY'] =  config['SECRET_KEY']
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite3'
app.config['BABEL_DEFAULT_LOCALE'] = config["DEFAULT_LOCALE"]

def get_locale():
    lang = request.args.get('lang','en')
    if not lang in config["AVAILABLE_LOCALE"]:
        lang = config["DEFAULT_LOCALE"]
    request.accept_languages.best_match(config["AVAILABLE_LOCALE"])
    return lang

babel = Babel(app,locale_selector=get_locale)

db.init_app(app)
migrate = Migrate(app, db)

login_manager.login_view = config["LOGIN_PATH"]

@login_manager.user_loader
def load_user(user_id):
    return User.query.get(int(user_id))

login_manager.init_app(app)

# register the route here
app.register_blueprint(auth.bp)

def create_app():
    g.debug = config["DEBUG"]
    return app
like image 39
Eren Avatar answered Oct 30 '25 18:10

Eren