processeur de contexte en utilisant Werkzeug et Jinja2
-
22-08-2019 - |
Question
Mon application est en cours d'exécution sur App Engine et est implémenté en utilisant Werkzeug et Jinja2 . Je voudrais avoir quelque chose fonctionnellement équivalent de processeur propre contexte de Django: une appelable qui prend une demande et ajoute quelque chose au contexte du modèle. J'ai déjà un « processeurs de contexte » qui ajoutent quelque chose au contexte du modèle, mais comment puis-je obtenir cette demande partiel? Je mis en œuvre des processeurs de contexte comme appelables qui reviennent juste un dictionnaire qui est utilisé plus tard pour mettre à jour le contexte.
Par exemple, je voudrais ajouter quelque chose qui est contenu dans request.environ
.
La solution
Une façon d'y parvenir est par le biais lié tardif modèle GLOBALS en utilisant le 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)
dans l'un de vos modèles, la demande actuelle apparaîtra lié à la variable « demande ». Bien sûr, cela pourrait être quelque chose d'autre dans environ. L'astuce consiste à utiliser le proxy local, puis définissez la valeur avant de vous rendre tout modèle.
Je devrais probablement aussi ajouter qu'un cadre comme (Werkzeug + Jinja2) Glashammer rationalise ce processus pour vous en utilisant les événements . De nombreuses fonctions peuvent se connecter aux événements au cours du processus de l'appel WSGI (par exemple, lorsqu'une demande est créée) et ils peuvent mettre des choses dans l'espace de noms de modèle à ce moment-là.
Autres conseils
Eh bien, en utilisant ce que Ali a écrit Je suis venu la solution qui est spécifique à App Engine (en raison de sa cache d'importation). Malheureusement, le code d'Ali ne fonctionne pas avec App Engine, car le code qui définit GLOBALS Jinja sont importés qu'une seule fois (ce qui globals efficacement statiques).
Je devais écrire ma propre fonction render()
et mettre à jour le contexte là. Pour être complet, voici le code que je suis venu à:
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 code d'Ali fonctionne comme prévu (et c'est la raison pour laquelle je retagging ma question).