UndefinedError:'user'未定义

lap*_*573 24 python nginx jinja2 flask uwsgi

我目前正在开发一个Flask应用程序(已经过去一年),我遇到了一个相当......奇怪的错误.我有一些文件总是包含在我的Jinja2模板(navbars)中,它们使用用户的名字和头像.因此,每次我渲染模板时,我都会将其传递给用户.我最近注意到我的prod服务器上有错误:

<img alt="image" 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
Run Code Online (Sandbox Code Playgroud)

这是我的一个导航栏.呈现此模板的方法使用此方法:

@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)
Run Code Online (Sandbox Code Playgroud)

如您所见,我传递了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())
Run Code Online (Sandbox Code Playgroud)

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

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

提前致谢.

pet*_*min 1

查看render_template 的 Flask 源

它只是调用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,
    ))
Run Code Online (Sandbox Code Playgroud)

如果这可行,我将需要深入了解谁修改了before_render_template插槽中的上下文。