具有动态 'secondary' 导航栏的 Flask-Nav

Flask-Nav with dynamic 'secondary' navbar

Flask-Nav allows dynamic construction;但是,我不知道如何通过将字典或列表传递给构建导航栏的函数来做到这一点。

@nav.navigation
def top_nav():
    # ...

根据文档,每次需要 Navbar 时都会调用它;但是,您可以执行类似 top_nav(items) 或类似的操作。

在我的 Jinja2 模板中,我用该页面的子菜单创建了一个字典(我想将其作为侧面菜单以及顶部固定导航栏)。我知道它可以通过宏的方式完成,但我很好奇是否有一种方法可以使用 Flask-Nav 来创建带有动态传递项目的辅助导航栏。

好吧,这个问题我真的来晚了,但我希望这可以帮助路过的人。我不完全明白你想如何继续(一些代码会有所帮助),但字典只是你可以解析并使用我将要描述的方法添加到导航栏的项目的集合。这些是我在项目中为侧边菜单创建动态导航栏的步骤(导航栏元素由各种模块添加):

  1. 创建导航栏:contextbar = Navbar('Context menu')(当然这需要 flask-nav 扩展)
  2. 将元素注册到导航栏:nav.register_element('contextbar', contextbar)
  3. create_app() 函数中初始化应用程序(这是一个标准的 Flask 工厂结构):nav.init_app(app)
  4. 对于我创建的每个 package/module,我将以下内容添加到 __init__.py 文件(当然,"application" 是我的应用程序的名称):

    from flask import current_app as app
    from flask_nav.elements import View
    from application import contextbar 
    
  5. 最后,仍然进入模块的 __init__.py 文件,我使用 @app.before_first_request 装饰器来确保导航栏添加只进行一次(而不是 each请求)避免重复项,代码如下

    # Add elements to the contextual navigation bar
    @app.before_first_request
    def before_first_request():
        contextbar.items.append(View('Meow', 'path.to.blueprint.meow'))
        contextbar.items.append(View('Bark', 'path.to.blueprint.bark'))
    

这样,每个模块都可以添加自己的菜单项(即使未请求该特定模块的路由)。为了完整起见,在 jinja2 模板中,您只需在希望导航栏呈现的位置添加代码 {{nav.contextbar.render()}}

我必须承认我对 Python、Flask 和朋友还很陌生,但这是我在我的 (test/tutorial/example) 项目中所做的,并且运行良好。

更新

我在使用 login/logout 时遇到了一些问题,因为在登录之前,用户未通过身份验证,导航栏将显示 "login",但之后导航栏不会更改(before_each_request 不会因为相同的 "session") 而再次触发,这并不好。所以,我切换到 before_request 有一点警告:

  1. 和以前一样
  2. 和以前一样
  3. 和以前一样
  4. 和以前一样
  5. 进入我的主应用程序的 routes.py 我添加以下代码来初始化导航栏并从 "no items"

    开始
    @app.before_request
    def before_request():
        # Only perform adding items to contextbar for non-static GET requests
        if request.method == 'GET' and request.endpoint not in ('static',):
            # Reset bar's items to avoid duplicates after each request
            contextbar.items = []
    
            # Add first link to the top bar
            contextbar.items.append(View('Home', 'homepage'))
    
  6. 在模块的每个 __init__.py 文件中,我从点“5”添加相同的代码,但没有重置导航栏项目:

    @app.before_request
    def before_request():
        # Only perform adding items to contextbar for non-static GET requests (POST requests usually do not need nav bars)
        if request.method == 'GET' and request.endpoint not in ('static',):
            # This is added to make sure these links are added only if the user is logged in
            if current_user.is_authenticated:
                contextbar.items.append(View('Bark', 'path.to.blueprint.bark'))
    
            # This link will be added to the navbar for logged in and out users
            contextbar.items.append(View('Meow', 'path.to.blueprint.meow'))
    

我是这样做的

from flask_nav import Nav
from flask_nav.elements import Navbar, View
from flask_login import current_user

nav = Nav()

@nav.navigation()
def mynavbar():
    if current_user.is_authenticated:
        return Navbar(
                    'Title',
                    View('Home', 'index'  ),
                    View('Servizi', 'servizi'  ),
                    View('Logout', 'logout'  )
                )
    else:
        return Navbar(
            'Title',
            View('Home', 'index'  ),
            View('Login', 'login'  )
        )

因此,如果用户已登录,我会显示更多项目