J'utilise la suite monkeypatch pour permettre légèrement plus d'informations utiles lorsqu'une exception se produit lors de Jinja2 modèle de rendu:
# Enabling this monkeypatch can help track down hard to find errors that crop
# up during template rendering (since Jinja's own error reporting is so
# unhelpful on AppEngine).
real_handle_exception = environment.handle_exception
def handle_exception(self, *args, **kwargs):
import logging, traceback
logging.error('Template exception:\n%s', traceback.format_exc())
real_handle_exception(self, *args, **kwargs)
environment.handle_exception = handle_exception
Cela aura pour résultat un peu plus précis exception retraçage dans vos journaux d'erreur. Je ne pense pas qu'il habituellement, vous montre exactement ce qui s'est passé (mais si je me souviens bien, il le fait parfois), mais il aura au moins étroit à l'exception vers le bas pour le modèle correct.
Pourquoi cela fonctionne, je ne sais pas (ou ne peuvent pas s'en rappeler).
Comme un exemple, j'ai juste ajouté un peu de code qui va déclencher une exception à l'un de mes modèles. Sous le serveur de développement, c'est ce que la "normale" gestionnaire d'exception m'indique:
Traceback (most recent call last):
File "/Users/will/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/google/appengine/ext/webapp/__init__.py", line 511, in __call__
handler.get(*groups)
File "/Users/will/workspace/keypremium/ki/shared/decorators.py", line 27, in inner
return func(self, *args, **kwargs)
File "/Users/will/workspace/keypremium/account/views.py", line 114, in get
self.render_jinja('accounts/edit_card.html', ctx)
File "/Users/will/workspace/keypremium/ki/webapp/handlers.py", line 186, in render_jinja
return self.response.out.write(jinja.render(template_path, new_context))
File "/Users/will/workspace/keypremium/ki/shared/jinja/__init__.py", line 21, in render
return template.render(context)
File "/Users/will/workspace/keypremium/ki/ext/jinja2/environment.py", line 705, in render
return self.environment.handle_exception(exc_info, True)
File "/Users/will/workspace/keypremium/ki/shared/jinja/environment.py", line 24, in handle_exception
real_handle_exception(self, *args, **kwargs)
File "/Users/will/workspace/keypremium/templates/accounts/edit_card.html", line 1, in top-level template code
{% extends 'accounts/base.html' %}
UndefinedError: 'sequence' is undefined
Mais l'exception n'est pas dans l' accounts/base.html
modèle, c'est en accounts/edit_card.html
. C'est la partie la plus frustrante de débogage Jinja2 modèle d'exception sur App Engine: La source de l'exception est presque toujours déformé. Dans mon expérience, la source est généralement signalé comme un parent, d'un modèle ou comme certains modèles de macro.
À l'exception de journalisation monkeypatch installé, la même exception génère cette de trace dans les logs:
Traceback (most recent call last):
File "/Users/will/workspace/keypremium/ki/ext/jinja2/environment.py", line 702, in render
return concat(self.root_render_func(self.new_context(vars)))
File "/Users/will/workspace/keypremium/templates/accounts/edit_card.html", line 11, in root
<div class="errors">
File "/Users/will/workspace/keypremium/templates/accounts/base.html", line 11, in root
</html>
File "/Users/will/workspace/keypremium/templates/accounts/edit_card.html", line 54, in block_content
<td>{{ form.cvv2|safe }}</td>
File "/Users/will/workspace/keypremium/ki/ext/jinja2/environment.py", line 352, in getattr
return getattr(obj, attribute)
File "/Users/will/workspace/keypremium/ki/ext/jinja2/runtime.py", line 445, in _fail_with_undefined_error
raise self._undefined_exception(hint)
UndefinedError: 'sequence' is undefined
Il y a encore beaucoup d'autres informations ici, mais ce traceback au moins des points de moi dans la bonne direction. Il affirme que le problème est à la ligne 54 accounts/edit_card.html
(le bon modèle), mais la véritable exception se produit à la ligne 86.
Mais étant donné le bon modèle et la bonne exception, je peux très facilement trouver que le gênants code est-ce
{% for x in sequence.sequence() %}
{{ x.y }}
{% endfor %}
où il n'y a pas d' sequence
variable dans le modèle de contexte.
Ce n'est pas une solution parfaite, mais je l'ai trouvé puissants utiles.