从 Flask Navigation 访问 Flask Session 变量以获取动态导航菜单
Accessing Flask Session variables from Flask Navigation for dynamic navigation menu
我想要一个动态导航菜单,如果用户当前未登录则显示 "Login",如果用户已登录则显示 "Logout"。
我使用的代码类似于以下内容:
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())
不幸的是,Flask 会话变量超出了导航对象的范围,因此我无法从 top_nav.
中访问 flask.session
当我在我的应用程序之外创建任何独立函数来访问 flask-session 时,我遇到了同样的困难,例如
def user_is_logged_in():
if 'google_token' in flask.session:
return True
else:
return False
return False
这些函数给出了预期的误差"RuntimeError: Working outside of request context."
出于安全原因,我不想在我的 application.py 代码中为用户使用全局变量,这样多人可以同时访问该应用程序而不会出错。我相信 SESSION 应该存储用户当前是否登录。
如何让我的 flask_nav.Nav() 看到我的应用程序的 flask.session?
Flask-Login 会让您的生活更轻松。它提供了一个 current_user
指向当前用户,用户对象有一个 is_authenticated
属性:
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"))
初始化 Flask-Login 的代码如下:
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)
查看 the documentation 了解更多详情。
flask_nav
在开始处理请求之前的应用程序生命周期中的某个阶段注册扩展。
当应用程序中存在请求上下文时,您可以稍后覆盖 template_global 的注册。
排除常见的导航项。
nav = Nav()
# registers the "top" menubar
navitems = [
View('Widgits, Inc.', 'index'),
View('Our Mission', 'about'),
]
根据会话
中的值将函数设置为return适当的View/Link
def with_user_session_action(items):
return (
items
+ [ View('Login', 'login') if not session.get('logged') else View('Logout', 'logout')]
)
在委托给 nav.register_element
的函数中使用它
def register_element(nav, navitems):
navitems = with_user_session_action(navitems)
return nav.register_element('top',
Navbar(*navitems)
)
取代render_template以始终传递计算的导航
_render_template = render_template
def render_template(*args, **kwargs):
register_element(nav, navitems)
return _render_template(*args, nav=nav.elems, **kwargs)
奖金:
您可以为 login/logout 缓存计算的导航,这样它就不会只为每个案例计算一次。
我想要一个动态导航菜单,如果用户当前未登录则显示 "Login",如果用户已登录则显示 "Logout"。
我使用的代码类似于以下内容:
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())
不幸的是,Flask 会话变量超出了导航对象的范围,因此我无法从 top_nav.
中访问 flask.session当我在我的应用程序之外创建任何独立函数来访问 flask-session 时,我遇到了同样的困难,例如
def user_is_logged_in():
if 'google_token' in flask.session:
return True
else:
return False
return False
这些函数给出了预期的误差"RuntimeError: Working outside of request context."
出于安全原因,我不想在我的 application.py 代码中为用户使用全局变量,这样多人可以同时访问该应用程序而不会出错。我相信 SESSION 应该存储用户当前是否登录。
如何让我的 flask_nav.Nav() 看到我的应用程序的 flask.session?
Flask-Login 会让您的生活更轻松。它提供了一个 current_user
指向当前用户,用户对象有一个 is_authenticated
属性:
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"))
初始化 Flask-Login 的代码如下:
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)
查看 the documentation 了解更多详情。
flask_nav
在开始处理请求之前的应用程序生命周期中的某个阶段注册扩展。
当应用程序中存在请求上下文时,您可以稍后覆盖 template_global 的注册。
排除常见的导航项。
nav = Nav()
# registers the "top" menubar
navitems = [
View('Widgits, Inc.', 'index'),
View('Our Mission', 'about'),
]
根据会话
中的值将函数设置为return适当的View/Linkdef with_user_session_action(items):
return (
items
+ [ View('Login', 'login') if not session.get('logged') else View('Logout', 'logout')]
)
在委托给 nav.register_element
的函数中使用它def register_element(nav, navitems):
navitems = with_user_session_action(navitems)
return nav.register_element('top',
Navbar(*navitems)
)
取代render_template以始终传递计算的导航
_render_template = render_template
def render_template(*args, **kwargs):
register_element(nav, navitems)
return _render_template(*args, nav=nav.elems, **kwargs)
奖金:
您可以为 login/logout 缓存计算的导航,这样它就不会只为每个案例计算一次。