2009-02-11 7 views
4

Mon application est en cours d'exécution sur App Engine et est mis en œuvre à l'aide Werkzeug et Jinja2. J'aimerais avoir quelque chose de fonctionnellement équivalent au propre processeur de contexte de Django: un callable qui accepte une requête et ajoute quelque chose au contexte du template. J'ai déjà un « processeurs de contexte » qui ajoutent quelque chose au contexte du modèle, mais comment puis-je obtenir cette demande travail partiel? J'ai implémenté des processeurs de contexte en tant que callables qui renvoient juste un dictionnaire qui sera utilisé plus tard pour mettre à jour le contexte.processeur de contexte à l'aide Werkzeug et Jinja2

Par exemple, je voudrais ajouter quelque chose qui est contenu dans request.environ.

+0

+1. Je souhaite que toutes les questions soient aussi bien formées que celle-ci. –

Répondre

4

L'une des façons d'atteindre cet objectif est de mettre en œuvre une liaison tardive template globals en utilisant thread-local proxy dans Werkzeug.

Un exemple simple qui met la demande dans les modèles les GLOBALS:

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) 

maintenant dans l'un de vos modèles, la demande actuelle apparaîtra lié à la variable « demande ». Bien sûr, cela pourrait être n'importe quoi d'autre dans environ. L'astuce consiste à utiliser le proxy local, puis définir la valeur avant de rendre n'importe quel modèle.

J'ajouterais probablement qu'un framework comme Glashammer (Werkzeug + Jinja2) rationalise ce processus pour vous en utilisant des événements. De nombreuses fonctions peuvent se connecter aux événements au cours du processus de l'appel WSGI (par exemple, lorsqu'une requête est créée) et ils peuvent placer des éléments dans l'espace de noms de modèle à ce stade.

+0

Le constructeur d'environnement ne prend pas l'argument "globals" - c'est un attribut de l'instance d'environnement (vous devez le modifier juste après avoir créé env). À part ça, c'est parfaitement ce que je cherchais. Je vous remercie. – zgoda

+0

Ah oui, merci, je vais mettre à jour l'exemple. Je l'ai fait de mémoire. –

+0

Malheureusement, cela ne peut pas être fait de cette façon avec AppEngine en raison du cache des imports (les modules importés sont mis en cache entre les requêtes) - les globals dict (et l'objet request) seraient mis en cache jusqu'au rechargement du module. – zgoda

3

Eh bien, en utilisant what Ali wrote je suis venu à la solution qui est spécifique à App Engine (en raison de son cache d'importation). Malheureusement, le code d'Ali ne fonctionne pas avec App Engine, car le code qui définit les globales Jinja n'est importé qu'une seule fois (ce qui rend les globals effectivement statiques).

je devais écrire ma propre fonction render() et mettre à jour le contexte là. Par souci d'exhaustivité, voici le code auquel je suis arrivé:

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) 

Ceci est spécifique à App Engine. Dans d'autres environnements, le code d'Ali fonctionne comme prévu (et c'est pourquoi je revérifie ma question).

Questions connexes