如何使用Flask将类变量传递到Jinja2模板中?

8

我有一个使用flask-login的模板,并且我已经建立了一个基于位集的权限模型。在我的模板中,我想根据权限公开页面上的内容。我在我的用户模型中有一个名为can(permission)的函数,用于控制用户可以做什么。

class User(UserMixin, db.Model):
    __tablename__ = 'users'
    id = db.Column(db.Integer, primary_key=True)
    email = db.Column(db.String(64), unique=True)
    fullname = db.Column(db.String(75))
    password_hash = db.Column(db.String(128))
    role_id = db.Column(db.Integer, db.ForeignKey('roles.id'))

    @property
    def password(self):
        raise AttributeError('password is not a readable attribute')

    @password.setter
    def password(self, password):
        self.password_hash = generate_password_hash(password)

    def verify_password(self, password):
        return check_password_hash(self.password_hash, password)

    def can(self, permissions):
        return self.role is not None and (self.role.permissions & permissions) == permissions

    def __repr__(self):
        return '<User: {}>'.format(self.email)

class Permission:
    FOLLOW = 0x01
    COMMENT = 0x02
    WRITE_ARTICLES = 0x04
    MODERATE_COMMENTS = 0x08
    ADMINISTER = 0x80

当我在模板中尝试调用can()函数并传递权限时,我会收到一个错误,指出Permission未定义,这可能是因为Permission类对于模板不在作用域内。以下是所有其他模板都继承的base.html的部分内容:
{% if current_user.can(Permission.ADMINISTER) %}
<h3>Administration</h3>
<ul>
    <li><a href="{{ url_for('main.add_user') }}">Add User</a></li>
    <li><a href="{{ url_for('main.change_password') }}">Change Password</a></li>
    <li><a href="{{ url_for('main.lock_user') }}">Lock User</a></li>
</ul>
{% endif %}

我正在松散地跟随Miguel Grinberg的《Flask Web Development》这本书,并且他在base.html(第32行)中做相同的事情。

我如何使Permission类在我的模板中可用?

1个回答

12

最明显的方法,但不是最方便的方法,就是在呈现需要它的模板时直接传递 Permission 类。

return render_template('page.html', Permission=Permission)

通过告诉Flask将其自动添加到模板上下文中,进一步实现此目的。 在设置应用程序时在某个位置装饰一个上下文处理器。


@app.context_processor
def include_permission_class():
    return {'Permission': Permission}

出于性能和清晰度的原因,上下文仅对即时渲染的模板可用。如果您需要在{% import %}{% include %}中使用它,则可以将with context添加到每个需要它的块中:{% include 'other_template.html' with context%}。或者,您可以将类添加到Jinja环境的全局命名空间中。

app.add_template_global(Permission, 'Permission')

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接