My goal is to make my home view (/
) a login page. Once the user logs in, a different page is render depending on its role. When I login (/auth
), I see that the username and password are correctly entered. It then attempts to render /
, where it tells me that my user is not authenticated and renders /login
. Here are the views that describe this:
Views
@app.route("/login")
def login():
return flask.render_template('login.html')
@app.route("/", methods=["GET"])
def home():
if current_user.is_authenticated:
if current_user.is_admin():
return flask.render_template('admin_index.html')
return flask.render_template('user_index.html')
logger.info("Not authenticated. Going back to login.")
return flask.render_template('login.html')
@app.route("/auth", methods=["POST"])
def auth():
username = request.form['username']
password = request.form['password']
user = db.session.query(User).filter(User.username == username).first()
logger.info(user)
logger.info("{0}: {1}".format(username, password))
print("user exists? {0}".format(str(user != None)))
print("password is correct? " + str(user.check_password(password)))
if user and user.check_password(password):
user.is_authenticated = True
login_user(user)
return flask.redirect(url_for('home'))
return flask.redirect(url_for('login'))
The problem is that flask-login's current_user.is_authenticated
is always returning False
after I attempt to login. My created user is correctly created and committed to the database. Below is my User model with the necessary methods as per flask-login:
User model
class User(db.Model):
"""
A user. More later.
"""
__tablename__ = 'User'
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(128), unique=True)
hashed_password = db.Column(db.String(160))
admin = db.Column(db.Boolean)
def __init__(self, username, password="changeme123", admin=False):
self.username = username
self.set_password(password)
self.admin = admin
self.is_authenticated = False
def is_active(self):
return True
def is_authenticated(self):
return self.is_authenticated
def is_anonymous(self):
return False
def is_admin(self):
return self.admin
def get_id(self):
return self.id
def __repr__(self):
return '<User {0}>'.format(self.username)
def set_password(self, password):
self.hashed_password = generate_password_hash(password)
def check_password(self, password):
return check_password_hash(self.hashed_password, password)
Here is the load_user
function:
load_user
@login_manager.user_loader
def load_user(user_id):
try:
return User.query.get(User.id==user_id)
except:
return None
Why is current_user.is_authenticated
returning False
? I presumed that login_user(user)
would make current_user == user
, i.e., the one who is being authenticated in /auth
, but it seems this is not the case.
You have a method named
User.is_authenticated
. InsideUser.__init__
, though, you set an attribute with the same name.This overrides the method. Then, whenever you check
current_user.is_authenticated
, you are accessing the attribute that's always false.You should remove the assignment from
__init__
and changeis_authenticated
to the following:If you need it to be dynamic for some reason, rename the attribute so it doesn't shadow the method.
Another problem is with your
load_user
function.Instead of
filter
ing forUser.id==user_id
, you areget
ting it. The user wasn't being returned becauseload_user
is returningUser.query.get(True)
instead ofUser.query.get(user_id)
.If you make the following change, it will work: