UndefinedError:“用户”未定义

Posted

技术标签:

【中文标题】UndefinedError:“用户”未定义【英文标题】:UndefinedError : 'user' is undefined 【发布时间】:2015-08-14 19:27:40 【问题描述】:

我目前正在开发一个 Flask 应用程序(过去一年一直如此),我遇到了一个相当……奇怪的错误。我的 Jinja2 模板(导航栏)中始终包含一些文件,它们使用用户名和头像。因此,每次渲染模板时,我都会将其传递给用户。我最近注意到我的产品服务器上有一个错误:

<img  class="img-circle" src=" user.image " style="width: 48px;"/>
  File "/usr/local/lib/python2.7/dist-packages/jinja2/environment.py", line 397, in getattr
    return getattr(obj, attribute)
jinja2.exceptions.UndefinedError: 'user' is undefined

这是在我的导航栏中之一。渲染这个模板的方法使用这个:

@mod.route('/broken_pus', methods=['POST', 'GET'])
def view_broken_pus():
    return render_template("view_broken_pus.html", user=g.user, urls_for_active_clients=DeletedURLs.objects()[0].urls_for_active_clients, other_urls=DeletedURLs.objects()[0].other_urls)

如您所见,我传递了 user=g.user。我在我网站的每一个视图上都这样做。它适用于任何地方,除了这种方法,它非常小。我有很多其他类似的路线,只有一个渲染模板,所以我不明白有什么问题。

我还通过另一种更大的方法得到它,以前总是有效的:

@mod.route('/users/add', methods=['GET', 'POST'])
@requires_roles("admin", "project-leader")
def add():
    """
    Method adding a new user.
    """
    # We do not use WTForms there since we need custom checkboxes for the role
    # Instead we use basic HTML and treat the checkboxes here
    if request.method == 'POST':
        user = User(name=request.form.get('name'),
                    email=request.form.get('email'))
        l = []
        # big switch assignement
        user.role = l
        try:
            user.save()
        except errors.NotUniqueError:
            flash(u'User %s already in database.' % user.name, 'danger')
            return redirect(url_for('home'))
        flash(u'User %s registered.' % user.name, 'success')
        return redirect(url_for('home'))
    return render_template('add_user.html', page=url_for('users.add'), user=g.user, clients=Client.objects())

当我第一次加载用于添加用户的表单时,它可以工作。当我添加它时,由于某种原因,我得到了错误(并且用户没有保存在数据库中)。

由于这在本地完美运行,我开始怀疑生产服务器本身存在问题。我们为应用程序使用 nginx 和 uwsgi,我最近实现了一些 Celery 任务。有什么想法吗?

提前致谢。

【问题讨论】:

你能在render_template之前打印g.user看看会发生什么吗? 它将它显示为一个用户对象,所以它似乎在这一点上被正确定义了! 您是否尝试过删除urls_for_active 的内容,只留下user=g.user 好的,现在这有点奇怪了。我按照你说的做了,页面加载正常,虽然它没有显示太多,因为它使用的所有数据都在另外两个参数中。但用户不再是问题。一旦我添加了其他两个参数之一,它就会再次因用户错误而崩溃!我已经尝试打印我的其他两个参数(两个包含元组的巨大列表),它们被正确填充并处于正常状态。知道他们为什么会导致这个错误吗?特别是因为它可以在本地使用尽可能多的数据。 我建议使用上下文处理器,这样全局对象就可用于所有模板,而无需将其传入:flask.pocoo.org/docs/0.10/templating/#context-processors 虽然这本身可能无法解决您的问题,但它会有所帮助你可以让你的代码更干净,更容易调试。您可以在我正在处理的项目中看到一个示例:主程序:github.com/kerryhatcher/sdf-tools/blob/master/SDFtools/… Auth 模块:github.com/kerryhatcher/sdf-tools/blob/master/SDFtools/auth/… 【参考方案1】:

查看烧瓶source for render_template:

它只是调用template.render(context),但在调用before_render_template.send(app, template=template, context=context)之后

由此,我认为有一些 before_render_template 处理程序,可以修改安装的上下文。

为了调试它,我可能会尝试这样调用:

from flask import app

@mod.route('/broken_pus', methods=['POST', 'GET'])
def view_broken_pus():
    template = app.jinja_env.get_or_select_template("view_broken_pus.html")
    return template.render(dict(
        user=g.user,
        urls_for_active_clients=DeletedURLs.objects()[0].urls_for_active_clients,
        other_urls=DeletedURLs.objects()[0].other_urls,
    ))

如果这可行,我将需要在before_render_template 插槽中挖掘谁修改了上下文。

【讨论】:

【参考方案2】:

我怀疑线程。如果 g 是某种全局引用,那么您可能需要确保它是在 threading.local 上设置的,或者使用线程锁来确保在某个“其他”线程与它发生冲突之前没有线程可以获取 g.user .

请参阅how do I make a 2.7 python context manager threadsafe,了解在不牺牲线程安全的情况下处理“全局”的方法。

【讨论】:

以上是关于UndefinedError:“用户”未定义的主要内容,如果未能解决你的问题,请参考以下文章

注意:未定义的索引:函数include()中的und [重复]

s3c2440裸机-异常中断(二. und未定义指令异常)

Flask / WTF表单将变量传递给模板会产生500错误,表单未定义

Mongoose 无法更新数组:未定义的错误

异常与中断2--und异常,swi异常,按键中断,定时器中断

GraphQL:必须是输出类型,但得到:未定义错误