Domanda

La mia applicazione è in esecuzione su App Engine ed è implementata utilizzando Werkzeug e Jinja2 . Mi piacerebbe avere qualcosa di funzionalmente equivalente del proprio contesto del processore di Django: un richiamabile che prende una richiesta e aggiunge qualcosa al contesto modello. Ho già un "contesto" di processori che aggiungono qualcosa al contesto modello, ma come faccio a questa richiesta parte di lavoro? Ho implementato processori contesto come callable che solo restituisce un dizionario che poi viene utilizzato per aggiornare contesto.

Per esempio, vorrei aggiungere qualcosa che è contenuto nel request.environ.

È stato utile?

Soluzione

Un modo per raggiungere questo obiettivo è attraverso tardiva template globali utilizzando il thread locale procura in Werkzeug.

Un semplice esempio che mette la richiesta nelle le variabili globali del modello:

from werkzeug import Local, LocalManager
local = Local()
local_manager = LocalManager([local])

from jinja2 import Environment, FileSystemLoader

# Create a global dict using the local's proxy to the request attribute
global_dict = {'request': local('request')}
jinja2_env = Environment(loader=FileSystemLoader('/'))
jinja2_env.globals.update(global_dict)

def application(environ, start_response):
    """A WSGI Application"""
    # later, bind the actual attribute to the local object
    local.request = request = Request(environ)

    # continue to view handling code
    # ...

application = local_manager.make_middleware(application)

Ora, in qualsiasi modello, la richiesta corrente, apparirà legata alla variabile "richiesta". Certo che potrebbe essere qualsiasi altra cosa nella environ. Il trucco è quello di utilizzare il proxy locale, quindi impostare il valore prima di rendere qualsiasi modello.

Probabilmente dovrei anche aggiungere che un quadro come Glashammer (Werkzeug + Jinja2) semplifica questo processo per voi utilizzando gli eventi . Molte funzioni possono connettersi agli eventi durante il processo della chiamata WSGI (ad esempio, quando viene creata una richiesta) e possono mettere la roba nello spazio dei nomi modello in quel punto.

Altri suggerimenti

Bene, utilizzando ciò che ha scritto Ali sono venuto a la soluzione che è specifico per App Engine (a causa della sua cache di importazione). Purtroppo, il codice di Ali non funziona con App Engine, perché il codice che imposta globali Jinja sono importate solo una volta (rendendo le variabili globali in modo efficace statiche).

ho dovuto scrivere la mia propria funzione render() e aggiornare il contesto lì. Per completezza, di seguito è il codice mi è venuto a:

def render(template, **kwargs):
    response_code = kwargs.pop('response_code', 200)
    mimetype = kwargs.pop('mimetype', 'text/html')
    for item in getattr(settings, 'CONTEXT_PROCESSORS', []):
        try:
            processor = import_string(item)
            kwargs.update(processor(local.request))
        except (ImportError, AttributeError), e:
            logging.error(e)
    return Response(jinja_env.get_template(template).render(**kwargs),
        status=response_code, mimetype=mimetype)

Si tratta di App Engine specifica. In altri ambienti codice di Ali funziona come previsto (ed è per questo che sto ricodifica la mia domanda).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top