#!/usr/bin/env python # -*- coding: utf-8 -*- import time from django import dispatch from django.core.signals import request_started from django.test.signals import template_rendered from django.conf import settings from django.db import connection from django.utils.encoding import force_unicode from django.utils.safestring import mark_safe USE_PYGMENTS = False try: import textwrap from pygments import highlight from pygments.formatters import HtmlFormatter from pygments.lexers import SqlLexer from pygments.styles import get_style_by_name USE_PYGMENTS = True except ImportError: pass if USE_PYGMENTS: WRAP = 120 STYLE = get_style_by_name('colorful') HEIGHT = '240px' # or '100%' if full height is wished TEMPLATE = """
+
""" # Monkeypatch instrumented test renderer from django.test.utils - we could use # django.test.utils.setup_test_environment for this but that would also set up # e-mail interception, which we don't want from django.test.utils import instrumented_test_render from django.template import Template, Context if Template.render != instrumented_test_render: Template.original_render = Template.render Template.render = instrumented_test_render # MONSTER monkey-patch old_template_init = Template.__init__ def new_template_init(self, template_string, origin=None, name=''): old_template_init(self, template_string, origin, name) self.origin = origin Template.__init__ = new_template_init class DebugFooter: def process_request(self, request): self.time_started = time.time() self.templates_used = [] self.contexts_used = [] self.sql_offset_start = len(connection.queries) my_signal = dispatch.Signal() my_signal.connect(self._storeRenderedTemplates) def process_response(self, request, response): if 'text/html' not in response['Content-Type']: return response if not settings.DEBUG: return response if response.status_code != 200: return response templates = [ (t.name, t.origin and t.origin.name or 'No origin') for t in self.templates_used ] sql_queries = connection.queries[self.sql_offset_start:] sql_total = 0.0 for query in sql_queries: query['sql'] = highlight_sql(query['sql']) sql_total += float(query['time']) debug_content = Template(TEMPLATE).render(Context({ 'server_time': time.time() - self.time_started, 'templates': templates, 'sql': sql_queries, 'sql_total': sql_total, 'template_dirs': settings.TEMPLATE_DIRS, 'height': 'height: %s;' % (HEIGHT, ), })) content = response.content if content.lower().count('``') > 0: response.content = force_unicode(content).replace('``', debug_content) + '``' else: response.content = force_unicode(content) + debug_content return response def _storeRenderedTemplates(self, signal, sender, template, context, **kwargs): self.templates_used.append(template) self.contexts_used.append(context) def highlight_sql(sql): if USE_PYGMENTS: sql = mark_safe(highlight(textwrap.fill(sql, WRAP), SqlLexer(encoding='utf-8'), HtmlFormatter(encoding='utf-8', noclasses=True, style=STYLE) ) ) else: sql = reformat_sql(sql) return sql def reformat_sql(sql): sql = sql.replace('`,`', '`, `') sql = sql.replace('` FROM `', '` \n FROM `') sql = sql.replace('` WHERE ', '` \n WHERE ') sql = sql.replace(' ORDER BY ', ' \n ORDER BY ') return sql