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 [重复]
Flask / WTF表单将变量传递给模板会产生500错误,表单未定义