Flask-Nav с динамическим "вторичным" navbar

Flask-Nav позволяет динамическое строительство; однако я не могу понять, как это сделать, передав словарь или список в функцию для построения Navbar.

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

Согласно документации, это вызывается каждый раз, когда нужен Navbar; тем не менее, вы можете сделать что-то вроде top_nav (items) или что-то подобное.

В моих шаблонах Jinja2 я создаю словарь с моим подменю для этой страницы (что я хочу сделать как боковое меню вместе с верхней фиксированной панелью навигации). Я знаю, что это можно сделать с помощью макросов, но мне было любопытно, если бы был способ использовать Flask-Nav для создания вторичного Navbar с динамически передаваемыми элементами.

0 ответов

Я сделал таким образом

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'  )
        )

поэтому, если пользователь вошел в систему, я показываю больше элементов

Что ж, я действительно очень опаздываю на этот вопрос, но я надеюсь, что это поможет людям, проходящим мимо. Я не совсем понимаю, как вы хотите действовать (небольшой код был бы полезен), но словарь - это просто набор элементов, которые вы можете проанализировать и добавить на панель навигации с помощью метода, который я собираюсь описать. Вот шаги, которые я использовал для создания динамической панели навигации для бокового меню в проекте (элементы панели навигации добавляются различными модулями):

  1. Создать панель навигации: contextbar = Navbar('Context menu') (для этого требуется flask-nav расширение, конечно)
  2. Зарегистрируйте элемент на панели навигации: nav.register_element('contextbar', contextbar)
  3. Инициализировать приложение в create_app() функция (это стандартная фабричная конструкция Flask): nav.init_app(app)
  4. Для каждого создаваемого пакета / модуля я добавляю следующее в __init__.py файл ("приложение" - это, конечно, название моего приложения):

    from flask import current_app as app
    from flask_nav.elements import View
    from application import contextbar 
    
  5. Наконец, все еще в __init__.py файл модулей, я использую @app.before_first_requestдекоратор, чтобы убедиться, что добавления навигационной панели выполняются только один раз (а не для каждого запроса), чтобы избежать дублирования элементов, и код выглядит следующим образом

    # 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 и друзьях, но это то, что я сделал в своем (тестовом / учебном / примере) проекте, и он работает хорошо.

ОБНОВИТЬ

У меня были некоторые проблемы с входом / выходом из системы, потому что перед входом пользователь не прошел проверку подлинности и на панели навигации будет отображаться "вход", но после этого панель навигации не изменится (before_each_requestне сработает снова для той же "сессии"), и это нехорошо. Итак, я перешел наbefore_request с маленьким пещерником:

  1. Как раньше
  2. Как раньше
  3. Как раньше
  4. Как раньше
  5. В routes.py своего основного приложения я добавляю следующий код для инициализации панели навигации и запуска с "без элементов"

    @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'))
    
Другие вопросы по тегам