Python 3.10 的 Flask Nav / 导航替代方案

Flask Nav / Navigation Alternative for Python 3.10

我目前正在制作一个 Flask 项目,但我需要能够在 render_template() return 页面时根据变量动态生成不同的导航栏。

更具体地说,我的目标是在以下情况下动态创建/ return 导航栏 1. 用户登录更改登录到帐户菜单 2. 类别的自层次结构(父类别FK ref in child node IF parent is root then FK is root) on a menu.

我对Flask还是个新手,但我一直在研究这件事,发现了Flask-Nav或Flask Navigation。这两个都不适合我,因为我在 Python 3.10 上是 运行,并且这两个库只在 Python 3.9 之前受支持。这是因为 Python 3.10 不支持可变序列。

lass ItemCollection(collections.MutableSequence, AttributeError: module 'collections' has no attribute 'MutableSequence'

是否有任何其他我可以使用的库或方法。我非常想生成我自己的 HTML 和 return,我一直坚持如何在实际模板之上说 return 导航 html 代码和将该代码放入靠近顶部但低于头部信息的导航位置。

string nav = '<NAV class='NavBar'><LINKS></NAV>'
return render_template('index.html', nav)

当用户登录时,您将用户详细信息分配给一个参数并将该参数传递回您的 front-end (html)。在您的前端,使用 JINJA2 检查参数是否存在。如果存在,显示 html 以获得帐户详细信息,否则显示登录 link。

粗略的样本是

html


<nav class="navbar navbar-expand-lg navbar-light bg-light">
  <a class="navbar-brand" href="#">Navbar</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>

  <div class="collapse navbar-collapse" id="navbarSupportedContent">
    <ul class="navbar-nav mr-auto">
      <!-- If user parameter exists, display Account and drop down -->
      {% if user %}
      <li class="nav-item dropdown">
        <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
         {{user.email}}
        </a>
        <div class="dropdown-menu" aria-labelledby="navbarDropdown">
          <a class="dropdown-item" href="#">Action 1</a>
          <a class="dropdown-item" href="#">Action 2</a>
        </div>
      </li>

    {% else %}
    <!-- User parameter does not exist so display login link -->
        <li class="nav-item active">
        <a class="nav-link" href="#">Home <span class="sr-only">Login</span></a>
      </li>
    {% endif %}
  </div>
</nav>

解决这个问题的方法可能是使用上下文处理器,它可以将变量注入每个路由...

from flask import Flask, render_template, url_for
app = Flask(__name__)

@app.context_processor 
def inject_dict_for_all_templates():
    """ Build the navbar and pass this to Jinja for every route
    """
    # Build the Navigation Bar
    nav = [
    {"text": "Homepage", "url": url_for('index')},
    {"text": "About Page", "url": url_for('about')},
    {
        "text": "More",
        "sublinks": [
            {"text": "Stack Overflow", "url": "https://whosebug.com"},
            {"text": "Google", "url": "https://google.com/"},
        ],
    },
    # {'text':'Github','url':'https://github.com/'}
    ]

    # sticking with the Flask login example

    if current_user.is_authenticated:
        # Show the user's name
        nav.append({'text': f'Logged in as {current_user.name}', 'url': url_for('profile')})
    else:
        # Show the login link
        nav.append({'text': 'Login', url_for('login')})

    return dict(navbar = nav)

当然,这里url_for函数是用来生成一些链接的,所以你也需要那些对应的路由...

@app.route('/')
def index(): return render_template('index.html')

@app.route('/about')
def about(): return render_template('about.html')

如果您使用 Flask-Login 之类的东西并且可以访问 currentuser 变量,您可能可以将其包含在 nav 词典列表中的某处。 (也许@NoCommandLine 的回答有更好的变量名信息)

这与 Bootstrap 的 navbar component 兼容,模板代码如下所示...

        <nav class="navbar navbar-expand-lg navbar-light bg-light">
          <a class="navbar-brand" href="#">{{config['SITE_TITLE']}}</a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
          </button>

          <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav mr-auto">
              
             {% for item in navbar %}
                {% if item.sublinks %}
                  <li class="nav-item dropdown">
                    <a class="nav-link dropdown-toggle" href="#" id="navbarDropdown" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                      {{item.text}}
                    </a>

                    <div class="dropdown-menu" aria-labelledby="navbarDropdown">

                        {% for sublink in item.sublinks %}
                              <a class='dropdown-item' href="{{sublink.url}}">{{sublink.text}}</a>
                        {% endfor %}
                    </div>
                  </li>

              {% elif item.url %}
                  <li class="nav-item">
                    <a class="nav-link" href="{{item.url}}">{{item.text}}</a>
                  </li>
              {% endif %}
              {% endfor %}
              </ul>

          </div>
        </nav>

呈现时,这会为您提供如下内容:

我已经创建了 a gist,其中包含基础模板和索引模板,以及正确的 CDN 链接以实现此功能。