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' )
)
поэтому, если пользователь вошел в систему, я показываю больше элементов
Что ж, я действительно очень опаздываю на этот вопрос, но я надеюсь, что это поможет людям, проходящим мимо. Я не совсем понимаю, как вы хотите действовать (небольшой код был бы полезен), но словарь - это просто набор элементов, которые вы можете проанализировать и добавить на панель навигации с помощью метода, который я собираюсь описать. Вот шаги, которые я использовал для создания динамической панели навигации для бокового меню в проекте (элементы панели навигации добавляются различными модулями):
- Создать панель навигации:
contextbar = Navbar('Context menu')
(для этого требуетсяflask-nav
расширение, конечно) - Зарегистрируйте элемент на панели навигации:
nav.register_element('contextbar', contextbar)
- Инициализировать приложение в
create_app()
функция (это стандартная фабричная конструкция Flask):nav.init_app(app)
Для каждого создаваемого пакета / модуля я добавляю следующее в
__init__.py
файл ("приложение" - это, конечно, название моего приложения):from flask import current_app as app from flask_nav.elements import View from application import contextbar
Наконец, все еще в
__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
с маленьким пещерником:
- Как раньше
- Как раньше
- Как раньше
- Как раньше
В
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'))
В каждую
__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'))