Can't access login_required routes with flask_login

1k Views Asked by At

I'm coding a simple flask app and I have already done all the login process. I'm not getting errors but the problem appears when I try to log in, somehow the program doesn't recognize me as a user, although I had already sign up correctly and my user data is in the database. So what ends happening is me trying to access to app_home route and, because it is a login_required route and the login doesn't save my data, I fall into a loop in the login page without being able to do anything.

Here is all the code:

server.py:

from flask import Flask
from flask_mongoengine import MongoEngine
from flask_login import LoginManager

from models import User

app = Flask(__name__)

...

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

@login_manager.user_loader
def load_user(email):
    return User.objects(email=email).first()

if __name__ == '__main__':
    app.run(debug=True)

models.py:

from flask_login import UserMixin
from mongo_setup import db

class User(UserMixin, db.Document):
    email = db.StringField()
    password = db.StringField()

auth.py:

from flask import Blueprint, render_template, redirect, url_for, request, flash
from werkzeug.security import generate_password_hash, check_password_hash
from flask_login import login_user, logout_user, login_required

auth = Blueprint('auth', __name__)

from mongo_setup import db
from models import User

...

@auth.route('/signup', methods=['GET', 'POST']) 
def signup():
    if request.method == 'POST':
        email = request.form.get('email')
        password = request.form.get('password')

        user_email = User.objects(email=email).first()

        if user_email: 
            flash("Email address already exists")
            return redirect(url_for('auth.signup'))

        User(email=email,
             password=generate_password_hash(password, method='sha256')
            ).save() 

    return render_template('signup.html')

@auth.route('/login') 
def login_get():
    return render_template('login.html')

@auth.route('/login', methods=['POST'])
def login():
    email = request.form.get("email")
    password = request.form.get("address")
    remember = True if request.form.get('remember') else False

    user = User.objects(email=email).first()

    if not user or not check_password_hash(user.password, password):
         flash('Please check your login details and try again.')
         return redirect(url_for('auth.login')) 

    login_user(user, remember=remember)
    return redirect(url_for('auth.app_home'))

@auth.route('/app/<address>/<data>/<delete>', methods=['GET', 'POST'])
@login_required
def app_home(address, data, delete):
    return render_template('app.html')
1

There are 1 best solutions below

0
raccoons On BEST ANSWER
@login_manager.user_loader
def load_user(id):
    return User.query.get(int(id))

You need to either change your load_user method to find the User object by id or overload the get_id() method on your User model to match your load_user() method to uniquely identify the user by email.

See: https://flask-login.readthedocs.io/en/latest/#how-it-works