Access Flask Navigation flag session variables for dynamic navigation menu

I want to have a dynamic navigation menu that displays "Login" if the user is not currently logged in, and "Logout" if the user is logged in.

I am using code similar to the following:

import flask import flask_nav import flask_nav.elements as fne frontend = flask.Blueprint('frontend', __name__) application = flask.Flask(__name__) mySess = flask_session.Session() flask_appconfig.AppConfig(application) flask_bootstrap.Bootstrap(application) application.register_blueprint(frontend) application.config['BOOTSTRAP_SERVE_LOCAL'] = True application.config['SSL'] = True application.secret_key = SECRET_KEY application.config['SESSION_TYPE'] = SESSION_TYPE mySess.init_app(application) nav = flask_nav.Nav() class CustomRenderer(flask_bootstrap.nav.BootstrapRenderer): def visit_Navbar(self, node): nav_tag = super(CustomRenderer, self).visit_Navbar(node) nav_tag['class'] = 'navbar navbar-default navbar-fixed-top' return nav_tag flask_nav.register_renderer(application, 'custom', CustomRenderer) nav.init_app(application) @nav.navigation() def top_nav(): items = [ fne.View('Home', '.index') ] if 'google_token' in flask.session: items.append(fne.View('Logout', '.logout')) elif 'auth_url' in flask.session: items.append(fne.View('Login', flask.session['auth_url'])) else: items.append(fne.View('Login', '.login')) items.append(fne.View('About', '.about')) items.append(fne.View('Contact', '.contact')) items.append(fne.View('Shop', '.shop')) items.append(fne.View('Help & Feedback', '.help')) return fne.Navbar('', *items) nav.register_element('frontend_top', top_nav()) 

Unfortunately, Flask session variables are out of scope for the nav object, so I cannot access flask.session from top_nav.

I have the same problem when I create a standalone function to access a flask session outside my application, for example

 def user_is_logged_in(): if 'google_token' in flask.session: return True else: return False return False 

These functions give the expected error "RuntimeError: Work out of request context".

I do not want to use the global variable in my application.py code for the user for security reasons, and therefore several people can access the application at the same time without errors. I believe that SESSION should be stored if the user is currently registered or not.

How do I get flask_nav.Nav () to see my flask.session application?

+3
source share
2 answers

flask_nav registers extensions at the application lifecycle stage before requests begin to be processed.

You can overwrite the registration of template_global later when the request context exists in the application.

Highlight common navigation items.

 nav = Nav() # registers the "top" menubar navitems = [ View('Widgits, Inc.', 'index'), View('Our Mission', 'about'), ] 

Set a function to return the corresponding view / link based on the value in the session

 def with_user_session_action(items): return ( items + [ View('Login', 'login') if not session.get('logged') else View('Logout', 'logout')] ) 

Use this in a function that delegates nav.register_element

 def register_element(nav, navitems): navitems = with_user_session_action(navitems) return nav.register_element('top', Navbar(*navitems) ) 

Supersede render_template always skips computed navigation

 _render_template = render_template def render_template(*args, **kwargs): register_element(nav, navitems) return _render_template(*args, nav=nav.elems, **kwargs) 

Bonus:

You can cache the computed nav for login / logout so that it will not only be computed once for each case.

+1
source

Flask-Login will make your life easier. He provided current_user to point to the current user, and the user object has the is_authenticated property:

 from flask_login import current_user ... @nav.navigation() def top_nav(): ... if current_user.is_authenticated: items.append(View("Logout", ".logout")) else: items.append(View("Login", ".login")) 

The code for initializing Flask-Login will look like this:

 from flask import Flask from flask_login import LoginManager, UserMixin app = Flask(__name__) login_manager = LoginManager(app) # The user model class User(db.Model, UserMixin): ... @login_manager.user_loader def load_user(user_id): return User.get(user_id) 

Read more about the documentation .

+1
source

All Articles