La risposta di Martin fornisce una buona spiegazione di perché questo errore si verifica.
La risposta accettata risolve il problema, ma non è certamente l'unico modo. Nel mio caso ho avuto qualcosa di più simile:
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))
Ma quando get_thing_from_datastore_render_and_cache_it
è stato eseguito in thread in background al di fuori del ciclo di richiesta Flask stavo ottenendo l'errore indicato sopra, perché quel filo non ha avuto accesso a un contesto richiesta.
L'errore si verifica perché Flask offre una scorciatoia sviluppatore per consentire l'accesso a variabili di richiesta nel modello automagically - in altre parole, essa è causata da decisioni Flask fatto su come avvolgere la funzionalità di Jinja2, non Jinja2 sé. Il mio approccio alla soluzione di questo era solo per usare Jinja2 di rendere direttamente:
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)
Tale funzione presuppone che il Flask applicazione ha il template tradizionale sottocartella. In particolare, la struttura del progetto qui sarebbe
.
└── name/
├── ofmy/
| ├── package/
| | ├── __init__.py <--- Where your Flask application object is defined
| | └── templates/
| | └── my_template.html
| └── __init__.py
└── __init__.py
Se si dispone di una struttura di sottodirectory sotto templates/
, basta passare il percorso relativo dalla radice dei modelli cartella lo stesso come si farebbe quando si utilizza Flask di render_template
.
Davvero un'ottima spiegazione. Non mi rendevo conto che era perché stavo correndo in un compito fuori dalla fiaschetta. –
Posso chiederti, come fai a sapere il nome del pacchetto? –