PageRenderTime 42ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/debug_toolbar/panels/template.py

https://github.com/mucca/django-debug-toolbar
Python | 122 lines | 102 code | 11 blank | 9 comment | 6 complexity | dfa51abca8e13ade1a6aa919a96a0ec6 MD5 | raw file
  1. from os.path import normpath
  2. from pprint import pformat
  3. from django import http
  4. from django.conf import settings
  5. from django.core.signals import request_started
  6. from django.dispatch import Signal
  7. from django.template.context import get_standard_processors
  8. from django.template.loader import render_to_string
  9. from django.test.signals import template_rendered
  10. from django.utils.translation import ugettext_lazy as _
  11. from debug_toolbar.panels import DebugPanel
  12. # Code taken and adapted from Simon Willison and Django Snippets:
  13. # http://www.djangosnippets.org/snippets/766/
  14. # Monkeypatch instrumented test renderer from django.test.utils - we could use
  15. # django.test.utils.setup_test_environment for this but that would also set up
  16. # e-mail interception, which we don't want
  17. from django.test.utils import instrumented_test_render
  18. from django.template import Template
  19. if not hasattr(Template, '_render'): # Django < 1.2
  20. if Template.render != instrumented_test_render:
  21. Template.original_render = Template.render
  22. Template.render = instrumented_test_render
  23. else:
  24. if Template._render != instrumented_test_render:
  25. Template.original_render = Template._render
  26. Template._render = instrumented_test_render
  27. # MONSTER monkey-patch
  28. old_template_init = Template.__init__
  29. def new_template_init(self, template_string, origin=None, name='<Unknown Template>'):
  30. old_template_init(self, template_string, origin, name)
  31. self.origin = origin
  32. Template.__init__ = new_template_init
  33. class TemplateDebugPanel(DebugPanel):
  34. """
  35. A panel that lists all templates used during processing of a response.
  36. """
  37. name = 'Template'
  38. has_content = True
  39. def __init__(self, *args, **kwargs):
  40. super(self.__class__, self).__init__(*args, **kwargs)
  41. self.templates = []
  42. template_rendered.connect(self._store_template_info)
  43. def _store_template_info(self, sender, **kwargs):
  44. self.templates.append(kwargs)
  45. def nav_title(self):
  46. return _('Templates')
  47. def title(self):
  48. num_templates = len([t for t in self.templates
  49. if not t['template'].name.startswith('debug_toolbar/')])
  50. return _('Templates (%(num_templates)s rendered)') % {'num_templates': num_templates}
  51. def url(self):
  52. return ''
  53. def process_request(self, request):
  54. self.request = request
  55. def content(self):
  56. context_processors = dict(
  57. [
  58. ("%s.%s" % (k.__module__, k.__name__),
  59. pformat(k(self.request))) for k in get_standard_processors()
  60. ]
  61. )
  62. template_context = []
  63. for template_data in self.templates:
  64. info = {}
  65. # Clean up some info about templates
  66. template = template_data.get('template', None)
  67. # Skip templates that we are generating through the debug toolbar.
  68. if template.name.startswith('debug_toolbar/'):
  69. continue
  70. if template.origin and template.origin.name:
  71. template.origin_name = template.origin.name
  72. else:
  73. template.origin_name = 'No origin'
  74. info['template'] = template
  75. # Clean up context for better readability
  76. if getattr(settings, 'DEBUG_TOOLBAR_CONFIG', {}).get('SHOW_TEMPLATE_CONTEXT', True):
  77. context_data = template_data.get('context', None)
  78. context_list = []
  79. for context_layer in context_data.dicts:
  80. if hasattr(context_layer, 'items'):
  81. for key, value in context_layer.items():
  82. # Replace any request elements - they have a large
  83. # unicode representation and the request data is
  84. # already made available from the Request Vars panel.
  85. if isinstance(value, http.HttpRequest):
  86. context_layer[key] = '<<request>>'
  87. # Replace the debugging sql_queries element. The SQL
  88. # data is already made available from the SQL panel.
  89. elif key == 'sql_queries' and isinstance(value, list):
  90. context_layer[key] = '<<sql_queries>>'
  91. # Replace LANGUAGES, which is available in i18n context processor
  92. elif key == 'LANGUAGES' and isinstance(value, tuple):
  93. context_layer[key] = '<<languages>>'
  94. try:
  95. context_list.append(pformat(context_layer))
  96. except UnicodeEncodeError:
  97. pass
  98. info['context'] = '\n'.join(context_list)
  99. template_context.append(info)
  100. context = self.context.copy()
  101. context.update({
  102. 'templates': template_context,
  103. 'template_dirs': [normpath(x) for x in settings.TEMPLATE_DIRS],
  104. 'context_processors': context_processors,
  105. })
  106. return render_to_string('debug_toolbar/panels/templates.html', context)