I have created a blueprint that handles authenticating. This blue print uses Flask-Login. And has the following, as well as more code not shown.
In the blueprint I have the following:
from flask.ext.login import LoginManager
from flask.ext.login import UserMixin
from flask.ext.login import current_user
from flask.ext.login import login_required
from flask.ext.login import login_user
from flask.ext.login import logout_user
auth_print = Blueprint('auth_print', __name__)
login_manager = LoginManager()
login_manager.login_view = '/login'
class User(UserMixin):
user_store = {} # Stores the users that are already logged in.
def __init__(self, user_id):
self.user_store[user_id] = self # add the user to the user_store
self.username = user_id # the user_id is in fact the username
self.id = unicode(user_id)
def sign_out(self):
logout_user()
try:
del self.user_store[self.id]
except KeyError:
pass
@classmethod
def get(cls, user_id):
return cls.user_store.get(user_id)
@login_manager.user_loader
def load_user(user_id):
return User.get(user_id)
def get_current_user():
return current_user
@login_required
@auth_print.route('/')
def user():
return "Welcome, and thanks for logging in."
Then I have a small app I would like to add authentication to.
Small App
import the_above_module
app.register_blueprint(the_above_module.auth_print) # register the blueprint
@the_above_module.login_required
@app.route('/profile')
def protected():
name = the_above_module.get_current_user().username
return "Thank you for logging in."
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)
Now I know the blueprint's @login_required is working because if I open the browser and go to localhost:8000/ I have to sign in.
However if I go to localhost:8000/profile the login_required decorator never gets triggered. I thus get an error because there is no current user.
Why would @login_required work in the blueprint and not in the app, even when im sure to maintain the same name spaces?
You have to change the order of the decorators. Quoting the Flask documentation:
So how would you use that decorator now? Apply it as innermost decorator to a view function. When applying further decorators, always remember that the route() decorator is the outermost:
@app.route('/secret_page') @login_required def secret_page(): pass