如何 show/hide 基于自定义装饰器管理员角色的导航栏项目

How to show/hide navbar item based on custom decorator admin role

decorators.py


from functools import wraps

from flask import flash, redirect, url_for
from flask_login import current_user


def admin_required(f):
    @wraps(f)
    def wrap(*args, **kwargs):
        if current_user.role == "Admin":
            return f(*args, **kwargs)
        else:
            flash("You need to be an admin to view this page.")
            return redirect(url_for('account'))

    return wrap

我可以使用 current_user.is_authenticated hide/show jinja 中的导航栏项目,但我似乎无法使用用户角色使其工作。有谁知道如何根据用户的角色更改基本模板中的导航栏项目?

base.html

            <div class="navbar-nav">
              {% if current_user.is_authenticated %}
                {{ render_nav_item('account', 'Account', use_li=True) }}
                {{ render_nav_item('logout', 'Logout', use_li=True) }}
              {% elif current_user.role == "Admin" %}
                {{ render_nav_item('admin_panel', 'Admin Panel', use_li=True) }}
              {% else %}
                {{ render_nav_item('login', 'Login', use_li=True) }}
              {% endif %}

            </div>

models.py

class User(db.Model, UserMixin):
    __tablename__ = 'users'

    id = db.Column(db.Integer, primary_key=True)
    weekly_time = db.relationship('WeeklyTime', backref=db.backref('user'), lazy=True)
    weekly_expense = db.relationship('WeeklyExpense', backref=db.backref('user'), lazy=True)

    name = db.Column(db.String(120), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    password = db.Column(db.String(120), nullable=False)
    account_creation_datetime = db.Column(db.DateTime, nullable=False)

    role = db.Column(db.String(45), nullable=False)
    confirmed = db.Column(db.Boolean, nullable=False, default=False)
    confirmed_on = db.Column(db.DateTime, nullable=True)
    password_reset_token = db.Column(db.String(120), nullable=True)


    def __repr__(self):
        return f"User('{self.name}', '{self.email}')"


管理员角色是否通过身份验证?也就是说,对于 Admin 角色,if current_user.is_authenticated 的计算结果是否为 True?在这种情况下,您的 if 语句在第一个条件下终止。您需要一个单独的 if 条件来测试经过身份验证的用户是否为管理员。

{% if current_user.is_authenticated %}
    {{ render_nav_item('account', 'Account', use_li=True) }}
    {{ render_nav_item('logout', 'Logout', use_li=True) }}
    {% if current_user.role == "Admin" %}
        {{ render_nav_item('admin_panel', 'Admin Panel', use_li=True) }}
    {% endif %}
{% else %}
    {{ render_nav_item('login', 'Login', use_li=True) }}
{% endif %}

只需在您的应用程序中声明两个顶部栏,top 和 top2 app.py:

...

from flask_login import UserMixin, LoginManager, login_required, current_user, login_user, logout_user
...

nav = Nav()

# registers the "top" menubar
nav.register_element('top', Navbar(logo,
                                   View('Home', 'index'),                                   
                                   View('LogIn', 'login'),  # login
                                   View('SignUp', 'signup'),  # signup
                                   ))
# registers the "top2" menubar
nav.register_element('top2', Navbar(logo,
                                    View('Home', 'index'),
                                    View('Profile', 'profile'),  # def profile                                    
                                    View('LogOut', 'logout'),  # def logout
                                    ))

现在在您的 base.html 中,您可以选择 with if block as:

<body>
    {% block navbar %}
        {% if current_user.is_authenticated %}
            {{nav.top2.render()}}
        {% else %} 
            {{nav.top.render()}}
        {% endif %}    
    {% endblock %}
...
</body>