<p>马丁的回答很好地解释了为什么会发生这个错误。</p>
<p>公认的答案解决了提出的问题,但肯定不是唯一的办法。在我的情况下,我有一些更像:</p>
<pre><code>import threading
from flask import Flask, render_template
app = Flask("myapp")
app.route('/')
def get_thing(thing_id):
thing = cache.get(thing_id)
if thing is None:
# Handle cache miss...
elif is_old(thing):
# We'll serve the stale content but let's
# update the cache in a background thread
t = threading.Thread(
target=get_thing_from_datastore_render_and_cache_it,
args=(thing_id,)
)
t.start()
return thing
def get_thing_from_datastore_render_and_cache_it(thing_id):
thing = datastore.get(thing_id)
cache.set(render_template(thing))
</code></pre>
<p>但是当<code>get_thing_from_datastore_render_and_cache_it</code>在Flask请求周期之外的后台线程中运行时,我得到了上面显示的错误,因为该线程没有访问请求上下文的权限。</p>
<p>之所以出现此错误,是因为Flask提供了一个开发人员快捷方式,允许自动访问模板中的请求变量—换句话说,这是Flask决定如何包装Jinja2的功能而不是Jinja2本身造成的。我解决这个问题的方法就是直接使用Jinja2的渲染:</p>
<pre><code>import jinja2
def render_without_request(template_name, **template_vars):
"""
Usage is the same as flask.render_template:
render_without_request('my_template.html', var1='foo', var2='bar')
"""
env = jinja2.Environment(
loader=jinja2.PackageLoader('name.ofmy.package','templates')
)
template = env.get_template(template_name)
return template.render(**template_vars)
</code></pre>
<p>该函数假定Flask应用程序具有传统模板子文件夹。具体来说,这里的项目结构是</p>
<pre><code>.
└── name/
├── ofmy/
| ├── package/
| | ├── __init__.py <--- Where your Flask application object is defined
| | └── templates/
| | └── my_template.html
| └── __init__.py
└── __init__.py
</code></pre>
<p>如果在<code>templates/</code>下有一个子目录结构,则只需从模板文件夹的根传递相对路径,就像使用Flask的<code>render_template</code>时一样。</p>