如何使用Flask为Jinja2模板提供类变量?

jca*_*e04 6 python jinja2 flask

我有一个使用flask-login的模板,我有一个基于bitset的权限模型.在我的模板中,我想基于权限公开页面中的内容.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
Run Code Online (Sandbox Code Playgroud)

当我尝试can()在模板中调用该函数并向其传递权限时,我收到一个错误,即未定义权限,可能是因为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 %}
Run Code Online (Sandbox Code Playgroud)

我正在松散地关注Miguel Grinberg关于Flask Web Development的书,他在base.html中做了同样的事情(第32行).

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

dav*_*ism 8

最明显的,但最不方便的是,只需Permission在渲染需要它的模板时传递类.

return render_template('page.html', Permission=Permission)
Run Code Online (Sandbox Code Playgroud)

通过告诉Flask 自动将其添加到模板上下文,更进一步.在设置应用程序时,在某处装饰上下文处理器.

@app.context_processor
def include_permission_class():
    return {'Permission': Permission}
Run Code Online (Sandbox Code Playgroud)

出于性能和清晰度原因,上下文仅对呈现的直接模板有效.如果您需要它,{% import %}或者{% include %}您可以添加with context到需要它的每个块:{% include 'other_template.html' with context%}.或者,您可以将该类添加到Jinja env的全局命名空间中.

app.add_template_global(Permission, 'Permission')
Run Code Online (Sandbox Code Playgroud)