如何在烧瓶中使用g.user global

时间:2012-11-29 01:12:23

标签: python flask jinja2 flask-login

正如我理解Flask中的g变量一样,它应该为我提供一个存储数据的全局位置,例如在登录后保存当前用户。这是对的吗?

我希望我的导航能够在整个网站上显示我的用户名称。

我的观点包含

from Flask import g #among other things

登录时,我指定

user = User.query.filter_by(username = form.username.data).first()
if validate(user):
    session['logged_in'] = True
    g.user = user

似乎我无法访问g.user。相反,当我的base.html模板具有以下内容时......

<ul class="nav">
    {% if session['logged_in'] %}
        <li class="inactive">logged in as {{ g.user.username }}</li>
    {% endif %}
</ul>

我收到错误:

jinja2.exceptions.UndefinedError
UndefinedError: 'flask.ctx._RequestGlobals object' has no attribute 'user'

登录其他方式正常。我错过了什么?

3 个答案:

答案 0 :(得分:74)

gthread local,是按请求的(请参阅A Note On Proxies)。 session 也是本地线程,但在默认上下文中持久保存到MAC签名的cookie并发送给客户端。

您遇到的问题是每次请求都会重建session(因为它被发送到客户端,客户端会将其发送回给我们),而g上设置的数据是仅在请求的生命周期内可用。

最简单的要做的事情(注意simple != secure - 如果你需要安全看看Flask-Login),只需将用户的ID添加到会话中并加载每个请求的用户:

@app.before_request
def load_user():
    if session["user_id"]:
        user = User.query.filter_by(username=session["user_id"]).first()
    else:
        user = {"name": "Guest"}  # Make it better, use an anonymous User instead

    g.user = user

答案 1 :(得分:11)

答案 2 :(得分:-16)

我会尝试一起摆脱全局变量,将您的应用程序视为执行任务的一组函数,每个函数都有输入和输出,不应该触及全局变量。只需获取您的用户并传递它,它就会使您的代码更易于测试。更好的是:摆脱烧瓶,烧瓶促进使用全球化,如

from flask import request