From ca99f4688fc70fb74bb2510a0aaaf4914a2c7aa9 Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Thu, 11 Sep 2008 15:31:02 -0700 Subject: Adding notes about the INTERNAL_IPS setting for this to work. --- README.rst | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.rst b/README.rst index 44aba49..2857fe9 100644 --- a/README.rst +++ b/README.rst @@ -36,6 +36,11 @@ Installation must come after any other middleware that encodes the response's content (such as GZipMiddleware). +#. Make sure your IP is listed in the `INTERNAL_IPS` setting. If you are + working locally this will be: + + INTERNAL_IPS = ('127.0.0.1',) + #. Add a tuple called `DEBUG_TOOLBAR_PANELS` to your ``settings.py`` file that specifies the full Python path to the panel that you want included in the Toolbar. This setting looks very much like the `MIDDLEWARE_CLASSES` setting. -- cgit v1.2.3 From 414368b6ec0ed856752dce752afad140a03c97f6 Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Thu, 11 Sep 2008 21:49:49 -0700 Subject: Patch submitted by Ned Batchelder to fix panel path slashes on Windows. --- debug_toolbar/templates/debug_toolbar/panels/templates.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debug_toolbar/templates/debug_toolbar/panels/templates.html b/debug_toolbar/templates/debug_toolbar/panels/templates.html index 58904be..f9f03b5 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/templates.html +++ b/debug_toolbar/templates/debug_toolbar/panels/templates.html @@ -12,8 +12,8 @@ {% if templates %}
{{ query.sql|escape }}{{ query.sql|wordwrap:80|escape }}{{ sql|wordwrap:80 }}| {{ h|upper }} | + {% endfor %} +
|---|
| {{ column|escape }} | + {% endfor %} +
{{ query.sql|wordwrap:80|escape }}'), response.content) return response diff --git a/debug_toolbar/templates/debug_toolbar/base.html b/debug_toolbar/templates/debug_toolbar/base.html index e654219..e1d66c5 100644 --- a/debug_toolbar/templates/debug_toolbar/base.html +++ b/debug_toolbar/templates/debug_toolbar/base.html @@ -1,5 +1,4 @@ - -- cgit v1.2.3 From 335cbb58f1681268eb61a04205b6a18f09f0a03a Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 20 Sep 2008 21:18:48 -0400 Subject: jquery now optional --- debug_toolbar/middleware.py | 6 +++++- debug_toolbar/templates/debug_toolbar/base.html | 1 - debug_toolbar/toolbar/loader.py | 3 +-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index 9c8581c..bb8dbbc 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -12,6 +12,7 @@ _HTML_TYPES = ('text/html', 'application/xhtml+xml') _END_HEAD_RE = re.compile(r'', re.IGNORECASE) _START_BODY_RE = re.compile(r'
', re.IGNORECASE) +_CONTAINS_JQUERY_RE = re.compile("src=(?:(\"(.*?)jquery(.*?)\.js\")|('(.*?)jquery(.*?)\.js'))", re.IGNORECASE) class DebugToolbarMiddleware(object): """ @@ -53,8 +54,11 @@ class DebugToolbarMiddleware(object): return response if self.show_toolbar(request): if response['Content-Type'].split(';')[0] in _HTML_TYPES: + script_loc = request.META.get('SCRIPT_NAME', '') # Saving this here in case we ever need to inject into
#response.content = _END_HEAD_RE.sub(smart_str(self.debug_toolbar.render_styles() + "%s" % match.group()), response.content) response.content = _START_BODY_RE.sub(smart_str('
'), response.content) + if not _CONTAINS_JQUERY_RE.search(response.content): + response.content = _END_BODY_RE.sub(smart_str('' % script_loc), response.content) + response.content = _END_BODY_RE.sub(smart_str('' % script_loc), response.content) return response diff --git a/debug_toolbar/templates/debug_toolbar/base.html b/debug_toolbar/templates/debug_toolbar/base.html index e1d66c5..ba13294 100644 --- a/debug_toolbar/templates/debug_toolbar/base.html +++ b/debug_toolbar/templates/debug_toolbar/base.html @@ -1,4 +1,3 @@ - diff --git a/debug_toolbar/toolbar/loader.py b/debug_toolbar/toolbar/loader.py index 935f45c..f45cbda 100644 --- a/debug_toolbar/toolbar/loader.py +++ b/debug_toolbar/toolbar/loader.py @@ -59,6 +59,5 @@ class DebugToolbar(object): Renders the overall Toolbar with panels inside. """ return render_to_string('debug_toolbar/base.html', { - 'panels': self.panels, - 'BASE_URL': self.request.META.get('SCRIPT_NAME', '') + 'panels': self.panels }) -- cgit v1.2.3 From 54c81b918db04b62a55f810d891de9dd71b57ab9 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 21 Sep 2008 11:56:43 -0400 Subject: pluralize query correctly, stolen from swillison --- debug_toolbar/panels/sql.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index 4b059ac..fd08395 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -39,7 +39,11 @@ class SQLDebugPanel(DebugPanel): def title(self): self._sql_time = sum(map(lambda q: float(q['time']) * 1000, connection.queries)) - return '%d SQL Queries (%.2fms)' % (len(connection.queries), self._sql_time) + return '%d SQL Quer%s (%.2fms)' % ( + len(connection.queries), + len(connection.queries) == 1 and 'y' or 'ies', + self._sql_time + ) def url(self): return '' -- cgit v1.2.3 From 9a7fe9e528c72d39efb1954275e1e588b2bb541c Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 21 Sep 2008 12:19:30 -0400 Subject: made jquery really optional, also switched to using google to serve jquery --- debug_toolbar/middleware.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index bb8dbbc..c17c424 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -12,7 +12,16 @@ _HTML_TYPES = ('text/html', 'application/xhtml+xml') _END_HEAD_RE = re.compile(r'', re.IGNORECASE) _START_BODY_RE = re.compile(r'
', re.IGNORECASE) -_CONTAINS_JQUERY_RE = re.compile("src=(?:(\"(.*?)jquery(.*?)\.js\")|('(.*?)jquery(.*?)\.js'))", re.IGNORECASE) + + +_JQUERY_OPTIONAL = """ + +""" class DebugToolbarMiddleware(object): """ @@ -58,7 +67,6 @@ class DebugToolbarMiddleware(object): # Saving this here in case we ever need to inject into
#response.content = _END_HEAD_RE.sub(smart_str(self.debug_toolbar.render_styles() + "%s" % match.group()), response.content) response.content = _START_BODY_RE.sub(smart_str('
' % script_loc), response.content) + response.content = _END_BODY_RE.sub(smart_str('%s' % _JQUERY_OPTIONAL), response.content) response.content = _END_BODY_RE.sub(smart_str('' % script_loc), response.content) return response -- cgit v1.2.3 From 48179eda15c81e08f8fc3db89468bb19e2f44ded Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Sun, 21 Sep 2008 21:48:51 -0700 Subject: Updated README a bit and added many of the suggestions to the TODO. --- README.rst | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/README.rst b/README.rst index 2bd8b87..2b30f5b 100644 --- a/README.rst +++ b/README.rst @@ -3,20 +3,18 @@ Django Debug Toolbar ==================== The Django Debug Toolbar is a configurable set of panels that display various -debug information about the current request/response. It is a small toolbar -that, when activated, situates itself in the top-right location of the browser -window. When particular panels are clicked, more details about that panel's -content are displayed. +debug information about the current request/response and when clicked, display +more details about the panel's content. Currently, the following panels have been written and are working: - Django version -- SQL queries including time to execute - Request timer - Common HTTP headers -- GET/POST variable display +- GET/POST/cookie/session variable display +- SQL queries including time to execute and links to EXPLAIN each query - Cache stats -- Templates used and template directories +- Templates and context used, and their template paths If you have ideas for other panels please let us know. @@ -71,3 +69,12 @@ TODO - Panel idea: Show some commonly used settings from settings.py - Panel idea: AJAX call to show cprofile data similar to the ?prof idea - CSS Stylings +- Move towards more explicit middleware style calls for panels in toolbar + middleware (e.g. panel.process_request) +- Restructure panels to popular context that pushes up to the toolbar +- Consider moving panel to the bottom of the HTML document, which would allow us + to use common reset.css for consistent toolbar styling without affecting + anything else. +- Make the trigger whether to display the toolbar configurable with options such + as if: DEBUG is true, IP is in INTERNAL_IPS, authenticated user is_superuser, + etc. -- cgit v1.2.3 From ee75a75f7e379b492af927b261726bc5d40fdb50 Mon Sep 17 00:00:00 2001 From: Simon Willison Date: Sat, 20 Sep 2008 23:31:45 +0100 Subject: Show 1 SQL query v.s. 3 SQL queries --- debug_toolbar/panels/sql.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index 4b059ac..81834b4 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -39,7 +39,11 @@ class SQLDebugPanel(DebugPanel): def title(self): self._sql_time = sum(map(lambda q: float(q['time']) * 1000, connection.queries)) - return '%d SQL Queries (%.2fms)' % (len(connection.queries), self._sql_time) + return '%d SQL %s (%.2fms)' % ( + len(connection.queries), + (len(connection.queries) == 1) and 'query' or 'queries', + self._sql_time + ) def url(self): return '' -- cgit v1.2.3 From ee810109f7dfb8c70278b5c447b4604bccc987a0 Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Sun, 21 Sep 2008 22:35:15 -0700 Subject: Refactoring middleware and panels so panels have more explicit middleware-like methods to be more clear when panel processing happens. --- debug_toolbar/middleware.py | 9 ++++++++- debug_toolbar/panels/__init__.py | 20 +++++++++++++++----- debug_toolbar/panels/cache.py | 3 +-- debug_toolbar/panels/headers.py | 7 ++++++- debug_toolbar/panels/request_vars.py | 3 +++ debug_toolbar/panels/sql.py | 6 +++--- debug_toolbar/panels/template.py | 6 ++---- debug_toolbar/panels/timer.py | 10 ++++++---- debug_toolbar/toolbar/loader.py | 8 ++++---- 9 files changed, 48 insertions(+), 24 deletions(-) diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index 9c8581c..0a202e2 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -44,13 +44,20 @@ class DebugToolbarMiddleware(object): if self.show_toolbar(request): self.debug_toolbar = DebugToolbar(request) - self.debug_toolbar.load_panels() + for panel in self.debug_toolbar.panels: + panel.process_request(request) return None + def process_view(self, request, view_func, view_args, view_kwargs): + for panel in self.debug_toolbar.panels: + panel.process_view(request, view_func, view_args, view_kwargs) + def process_response(self, request, response): if response.status_code != 200: return response + for panel in self.debug_toolbar.panels: + panel.process_response(request, response) if self.show_toolbar(request): if response['Content-Type'].split(';')[0] in _HTML_TYPES: # Saving this here in case we ever need to inject into
diff --git a/debug_toolbar/panels/__init__.py b/debug_toolbar/panels/__init__.py index 29cec02..54b3318 100644 --- a/debug_toolbar/panels/__init__.py +++ b/debug_toolbar/panels/__init__.py @@ -6,9 +6,10 @@ class DebugPanel(object): """ # name = Base has_content = False # If content returns something, set to true in subclass - - def __init__(self, request): - self.request = request + + # Panel methods + def __init__(self): + pass def dom_id(self): return 'djDebug%sPanel' % (self.name.replace(' ', '')) @@ -20,6 +21,15 @@ class DebugPanel(object): raise NotImplementedError def content(self): - # TODO: This is a bit flaky in that panel.content() returns a string - # that gets inserted into the toolbar HTML template. raise NotImplementedError + + # Standard middleware methods + def process_request(self, request): + pass + + def process_view(self, request, view_func, view_args, view_kwargs): + pass + + def process_response(self, request, response): + pass + diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py index 263b62b..613d4d9 100644 --- a/debug_toolbar/panels/cache.py +++ b/debug_toolbar/panels/cache.py @@ -78,7 +78,7 @@ class CacheDebugPanel(DebugPanel): name = 'Cache' has_content = True - def __init__(self, request): + def __init__(self): # This is hackish but to prevent threading issues is somewhat needed if isinstance(cache.cache, CacheStatTracker): cache.cache.reset() @@ -86,7 +86,6 @@ class CacheDebugPanel(DebugPanel): else: self.cache = CacheStatTracker(cache.cache) cache.cache = self.cache - super(CacheDebugPanel, self).__init__(request) def title(self): return 'Cache: %.2fms' % self.cache.total_time diff --git a/debug_toolbar/panels/headers.py b/debug_toolbar/panels/headers.py index 3ab4a95..213198a 100644 --- a/debug_toolbar/panels/headers.py +++ b/debug_toolbar/panels/headers.py @@ -37,8 +37,13 @@ class HeaderDebugPanel(DebugPanel): def url(self): return '' + def process_request(self, request): + self.headers = dict( + [(k, request.META[k]) for k in self.header_filter if k in request.META] + ) + def content(self): context = { - 'headers': dict([(k, self.request.META[k]) for k in self.header_filter if k in self.request.META]), + 'headers': self.headers } return render_to_string('debug_toolbar/panels/headers.html', context) \ No newline at end of file diff --git a/debug_toolbar/panels/request_vars.py b/debug_toolbar/panels/request_vars.py index a137393..88a7204 100644 --- a/debug_toolbar/panels/request_vars.py +++ b/debug_toolbar/panels/request_vars.py @@ -14,6 +14,9 @@ class RequestVarsDebugPanel(DebugPanel): def url(self): return '' + def process_request(self, request): + self.request = request + def content(self): context = { 'get': [(k, self.request.GET.getlist(k)) for k in self.request.GET.iterkeys()], diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index 81834b4..b99709f 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -27,13 +27,13 @@ util.CursorDebugWrapper = DatabaseStatTracker class SQLDebugPanel(DebugPanel): """ - Panel that displays information about the SQL queries run while processing the request. + Panel that displays information about the SQL queries run while processing + the request. """ name = 'SQL' has_content = True - def __init__(self, request): - super(SQLDebugPanel, self).__init__(request) + def __init__(self): self._offset = len(connection.queries) self._sql_time = 0 diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template.py index e08f220..eb20079 100644 --- a/debug_toolbar/panels/template.py +++ b/debug_toolbar/panels/template.py @@ -1,3 +1,4 @@ +from pprint import pformat from django.conf import settings from django.core.signals import request_started from django.dispatch import Signal @@ -5,8 +6,6 @@ from django.template.loader import render_to_string from django.test.signals import template_rendered from debug_toolbar.panels import DebugPanel -from pprint import pformat - # Code taken and adapted from Simon Willison and Django Snippets: # http://www.djangosnippets.org/snippets/766/ @@ -32,8 +31,7 @@ class TemplateDebugPanel(DebugPanel): name = 'Template' has_content = True - def __init__(self, request): - super(TemplateDebugPanel, self).__init__(request) + def __init__(self): self.templates = [] template_rendered.connect(self._storeTemplateInfo) diff --git a/debug_toolbar/panels/timer.py b/debug_toolbar/panels/timer.py index d520191..ea8ed4a 100644 --- a/debug_toolbar/panels/timer.py +++ b/debug_toolbar/panels/timer.py @@ -3,16 +3,18 @@ from debug_toolbar.panels import DebugPanel class TimerDebugPanel(DebugPanel): """ - Panel that displays the time a response took. + Panel that displays the time a response took in milliseconds. """ name = 'Timer' - def __init__(self, request): - super(TimerDebugPanel, self).__init__(request) + def process_request(self, request): self._start_time = time.time() + def process_response(self, request, response): + self.total_time = (time.time() - self._start_time) * 1000 + def title(self): - return 'Time: %0.2fms' % ((time.time() - self._start_time) * 1000) + return 'Time: %0.2fms' % (self.total_time) def url(self): return '' diff --git a/debug_toolbar/toolbar/loader.py b/debug_toolbar/toolbar/loader.py index 935f45c..56da11b 100644 --- a/debug_toolbar/toolbar/loader.py +++ b/debug_toolbar/toolbar/loader.py @@ -8,8 +8,6 @@ class DebugToolbar(object): def __init__(self, request): self.request = request self.panels = [] - self.panel_list = [] - self.content_list = [] # Override this tuple by copying to settings.py as `DEBUG_TOOLBAR_PANELS` self.default_panels = ( 'debug_toolbar.panels.version.VersionDebugPanel', @@ -20,7 +18,8 @@ class DebugToolbar(object): 'debug_toolbar.panels.cache.CacheDebugPanel', 'debug_toolbar.panels.template.TemplateDebugPanel', ) - + self.load_panels() + def load_panels(self): """ Populate debug panels @@ -48,8 +47,9 @@ class DebugToolbar(object): raise exceptions.ImproperlyConfigured, 'Toolbar Panel module "%s" does not define a "%s" class' % (panel_module, panel_classname) try: - panel_instance = panel_class(self.request) + panel_instance = panel_class() except: + print panel_class raise # Bubble up problem loading panel self.panels.append(panel_instance) -- cgit v1.2.3 From 358db8a2c75c76384728a71bf6a727178a848cc2 Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Sun, 21 Sep 2008 22:36:03 -0700 Subject: Removing update from previous commit from TODO list in README. --- README.rst | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.rst b/README.rst index 2b30f5b..c5e4c5f 100644 --- a/README.rst +++ b/README.rst @@ -69,8 +69,6 @@ TODO - Panel idea: Show some commonly used settings from settings.py - Panel idea: AJAX call to show cprofile data similar to the ?prof idea - CSS Stylings -- Move towards more explicit middleware style calls for panels in toolbar - middleware (e.g. panel.process_request) - Restructure panels to popular context that pushes up to the toolbar - Consider moving panel to the bottom of the HTML document, which would allow us to use common reset.css for consistent toolbar styling without affecting -- cgit v1.2.3 From c09b0dbc6e7cefd075819e6a272067f03b8534f1 Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Sun, 21 Sep 2008 22:48:45 -0700 Subject: Load jQuery only if jQuery isn't already loaded. Patch from Alex Gaynor slightly modified to load jQuery locally to allow offline usage. --- debug_toolbar/templates/debug_toolbar/base.html | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/debug_toolbar/templates/debug_toolbar/base.html b/debug_toolbar/templates/debug_toolbar/base.html index e1d66c5..f9844a1 100644 --- a/debug_toolbar/templates/debug_toolbar/base.html +++ b/debug_toolbar/templates/debug_toolbar/base.html @@ -1,4 +1,9 @@ - + -- cgit v1.2.3 From 276e1c284aa976f69c68230591b9f7fd1fbbc676 Mon Sep 17 00:00:00 2001 From: Bryan Veloso Date: Mon, 22 Sep 2008 18:19:32 -0700 Subject: Committing my first run at the new CSS. This is a bit old. Old being a few days old. --- debug_toolbar/media/toolbar.css | 145 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 131 insertions(+), 14 deletions(-) diff --git a/debug_toolbar/media/toolbar.css b/debug_toolbar/media/toolbar.css index 11dd978..fb347df 100644 --- a/debug_toolbar/media/toolbar.css +++ b/debug_toolbar/media/toolbar.css @@ -1,14 +1,131 @@ -#djDebugToolbar {height:30px; background:orange; color:#000; z-index:100000000; border:1px solid #06171D; border-width:1px 0;} -#djDebugToolbar ul {margin:0; padding:0 10px; list-style:none;} -#djDebugToolbar li {display:inline; width:auto; position:relative; float:none; margin:0 10px 0 0; padding:0; height:20px; line-height:30px; padding:8px 10px 8px 0; border-right: 1px solid #06171D;} -#djDebugToolbar #djDebugButton {color:red; font-weight:bold;} -#djDebug * {margin:0; padding:0; float:none; position:static; } -#djDebug .panelContent {display:none; position:absolute; margin:0; padding:5px; top:35px; width:auto; left:5px; right:5px; bottom:5px; background:white; color:black; border:1px solid black; z-index:1000000; overflow:auto;} -#djDebug .panelContent p {padding: 0 5px;} -#djDebug .panelContent p, #djDebug .panelContent table, #djDebug .panelContent ul, #djDebug .panelContent dl {margin:5px 0;} -#djDebug .close {float:right; font-weight:bold;} -#djDebug .panelContent dt, #djDebug .panelContent dd {display: block;} -#djDebug .panelContent dd {margin-left:10px;} -#djDebug th, #djDebug td {padding: 5px;} -#djDebug .row1 td {background:#fff;} -#djDebug .row2 td {background:#ddd;} +/* @override http://projectrenova.com:9000/__debug__/m/toolbar.css */ + +#djDebugToolbar { + background: #326342; + height: 30px; + z-index: 100000000; + border-bottom: 2px solid #234f32; +} + +#djDebugToolbar ul { + margin: 0; + padding: 0; + list-style: none; +} + +#djDebugToolbar li { + border-left: 1px solid #487858; + color: #fff; + display: inline; + font-size: 11px; + font-weight: bold; + float: none; + height: 20px; + margin: 0; + padding: 0; + line-height: 30px; + padding: 8px 10px 9px; + position: relative; + width: auto; +} + +#djDebugToolbar li:hover { + background: #487858; +} + +#djDebugToolbar li:hover a { + color: #fff; +} + +#djDebugToolbar li:last-child { + border-right: 1px solid #487858; +} + +#djDebugToolbar #djDebugButton { + color: #92ef3f; +} + +#djDebug * { + color: #fff; + text-shadow: 0 0 2px #333; + float: none; + margin: 0; + padding: 0; + position: static; +} + +#djDebug a { + color: #f7c757; +} + +#djDebug a:hover { + color: #fff; +} + + +#djDebug .panelContent { + background: #2a5738; + border-bottom: 2px solid #234f32; + border-top: 2px solid #487858; + display: none; + position: absolute; + margin: 0; + padding: 10px; + top: 35px; + width: auto; + left: 0px; + right: 0px; + bottom: 5px; + color: black; + z-index: 1000000; + overflow: auto; +} + +#djDebug h3 { + border-bottom: 1px solid #40684c; + color: #92ef3f; + padding: 0 0 5px; +} + +#djDebug .panelContent p { + padding: 0 5px; +} + +#djDebug .panelContent p, #djDebug .panelContent table, #djDebug .panelContent ol, #djDebug .panelContent ul, #djDebug .panelContent dl { + margin: 5px 0 15px; +} + +#djDebug .panelContent table { + width: 100%; +} + +#djDebug .close { + float: right; + font-weight: bold; +} + +#djDebug .panelContent dt, #djDebug .panelContent dd { + display: block; +} + +#djDebug .panelContent dd { + margin-left: 10px; +} + +#djDebug th { + font-weight: bold; + text-align: left; + padding: 5px; +} + +#djDebug td { + padding: 5px; +} + +#djDebug .row1 td { + background: #40684c; +} + +#djDebug .row2 td { + background: #356042; +} \ No newline at end of file -- cgit v1.2.3 From fb5788d8643320724a65890ce3df86d5e2bf591b Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Tue, 23 Sep 2008 10:27:23 -0700 Subject: Possible fix for jQuery.noConflict() removing '$' from scope and breaking other scripts that depend on it. --- debug_toolbar/media/toolbar.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/debug_toolbar/media/toolbar.js b/debug_toolbar/media/toolbar.js index 19a6abf..455a2fc 100644 --- a/debug_toolbar/media/toolbar.js +++ b/debug_toolbar/media/toolbar.js @@ -1,3 +1,4 @@ +var _$ = window.$; jQuery.noConflict(); jQuery(function($) { $.djDebug = function(data, klass) { @@ -62,3 +63,4 @@ jQuery(function($) { jQuery(function() { jQuery.djDebug(); }); +$ = _$; -- cgit v1.2.3 From f4d0f529a31ec4904501c43b2bd847b440fd5c08 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Sun, 21 Sep 2008 10:47:05 +1000 Subject: A couple of small HTML and presentation cleanups. - Don't display the headings of the detailed usage table for the cache panel unless there's actually some content to display. - Use pluralisation filter on the template paths to avoid "path(s)". - If there are no templates used or no template paths, wrap "None" in a paragraph tag. --- debug_toolbar/templates/debug_toolbar/panels/cache.html | 3 ++- debug_toolbar/templates/debug_toolbar/panels/templates.html | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/debug_toolbar/templates/debug_toolbar/panels/cache.html b/debug_toolbar/templates/debug_toolbar/panels/cache.html index 21ea173..0dad9b1 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/cache.html +++ b/debug_toolbar/templates/debug_toolbar/panels/cache.html @@ -31,6 +31,7 @@
+{% if cache.calls %}
\ No newline at end of file +{% endif %} diff --git a/debug_toolbar/templates/debug_toolbar/panels/templates.html b/debug_toolbar/templates/debug_toolbar/panels/templates.html index 575d507..a0e1c1c 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/templates.html +++ b/debug_toolbar/templates/debug_toolbar/panels/templates.html @@ -1,4 +1,4 @@ -
+
{% if template_dirs %}
{% else %} - None +
None
{% endif %}
{% if templates %} @@ -21,5 +21,5 @@ {% endfor %} {% else %} - None +
None
{% endif %} -- cgit v1.2.3 From 864fde8eab5074a89281873e75e8a9a97fc7109d Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Wed, 24 Sep 2008 10:52:06 +1000 Subject: The start of some work to make the CSS play nicely with others. Right now, if you use the debug toolbar in a site that also uses YUI's grid system, all the text will be centre-aligned. So this commit pushes it back to left-aligned. There are still some more workaround stylings required here (spacing, font un-breakage, etc), but this solves the most immediate problem. --- debug_toolbar/media/toolbar.css | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debug_toolbar/media/toolbar.css b/debug_toolbar/media/toolbar.css index 7d2ad82..7fd5cc5 100644 --- a/debug_toolbar/media/toolbar.css +++ b/debug_toolbar/media/toolbar.css @@ -1,8 +1,8 @@ -#djDebugToolbar {height:30px; background:orange; color:#000; z-index:100000000; border:1px solid #06171D; border-width:1px 0;} +#djDebugToolbar {height:30px; background:orange; color:#000; z-index:100000000; border:1px solid #06171D; border-width:1px 0; text-align: left;} #djDebugToolbar ul {margin:0; padding:0 10px; list-style:none;} #djDebugToolbar li {display:inline; width:auto; position:relative; float:none; margin:0 10px 0 0; padding:0; height:20px; line-height:30px; padding:8px 10px 8px 0; border-right: 1px solid #06171D;} #djDebugToolbar #djDebugButton {color:red; font-weight:bold;} -#djDebug * {margin:0; padding:0; float:none; position:static; } +#djDebug * {margin:0; padding:0; float:none; position:static; text-align: left;} #djDebug .panelContent {display:none; position:absolute; margin:0; padding:5px; top:35px; width:auto; left:5px; right:5px; bottom:5px; background:white; color:black; border:1px solid black; z-index:1000000; overflow:auto;} #djDebug .panelContent p {padding: 0 5px;} #djDebug .panelContent p, #djDebug .panelContent table, #djDebug .panelContent ul, #djDebug .panelContent dl {margin:5px 0;} -- cgit v1.2.3 From 7ea7e780b775680be3050a8d6eb71f63b5a1fd34 Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Tue, 23 Sep 2008 19:55:18 -0700 Subject: Updating pygments styles to better match new toolbar styles. --- debug_toolbar/media/toolbar.css | 83 +++++++++++++++++++--- debug_toolbar/panels/sql.py | 2 +- .../templates/debug_toolbar/panels/sql.html | 4 +- 3 files changed, 78 insertions(+), 11 deletions(-) diff --git a/debug_toolbar/media/toolbar.css b/debug_toolbar/media/toolbar.css index 7c37f03..b1fae96 100644 --- a/debug_toolbar/media/toolbar.css +++ b/debug_toolbar/media/toolbar.css @@ -28,15 +28,15 @@ } #djDebugToolbar li:hover { - background: #487858; + background: #487858; } #djDebugToolbar li:hover a { - color: #fff; + color: #fff; } #djDebugToolbar li:last-child { - border-right: 1px solid #487858; + border-right: 1px solid #487858; } #djDebugToolbar #djDebugButton { @@ -53,14 +53,13 @@ } #djDebug a { - color: #f7c757; + color: #f7c757; } #djDebug a:hover { - color: #fff; + color: #fff; } - #djDebug .panelContent { background: #2a5738; border-bottom: 2px solid #234f32; @@ -90,7 +89,7 @@ } #djDebug .panelContent p, #djDebug .panelContent table, #djDebug .panelContent ol, #djDebug .panelContent ul, #djDebug .panelContent dl { - margin: 5px 0 15px; + margin: 5px 0 15px; } #djDebug .panelContent table { @@ -126,4 +125,72 @@ #djDebug .row2 td { background: #356042; -} \ No newline at end of file +} +#djDebug .syntax { background: #111111; color: #ffffff } +#djDebug .syntax .c { color: #008800; font-style: italic; background-color: #0f140f } /* Comment */ +#djDebug .syntax .err { color: #ffffff } /* Error */ +#djDebug .syntax .g { color: #ffffff } /* Generic */ +#djDebug .syntax .k { color: #fb660a; font-weight: bold } /* Keyword */ +#djDebug .syntax .l { color: #ffffff } /* Literal */ +#djDebug .syntax .n { color: #ffffff } /* Name */ +#djDebug .syntax .o { color: #ffffff } /* Operator */ +#djDebug .syntax .x { color: #ffffff } /* Other */ +#djDebug .syntax .p { color: #ffffff } /* Punctuation */ +#djDebug .syntax .cm { color: #008800; font-style: italic; background-color: #0f140f } /* Comment.Multiline */ +#djDebug .syntax .cp { color: #ff0007; font-weight: bold; font-style: italic; background-color: #0f140f } /* Comment.Preproc */ +#djDebug .syntax .c1 { color: #008800; font-style: italic; background-color: #0f140f } /* Comment.Single */ +#djDebug .syntax .cs { color: #008800; font-style: italic; background-color: #0f140f } /* Comment.Special */ +#djDebug .syntax .gd { color: #ffffff } /* Generic.Deleted */ +#djDebug .syntax .ge { color: #ffffff } /* Generic.Emph */ +#djDebug .syntax .gr { color: #ffffff } /* Generic.Error */ +#djDebug .syntax .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */ +#djDebug .syntax .gi { color: #ffffff } /* Generic.Inserted */ +#djDebug .syntax .go { color: #444444; background-color: #222222 } /* Generic.Output */ +#djDebug .syntax .gp { color: #ffffff } /* Generic.Prompt */ +#djDebug .syntax .gs { color: #ffffff } /* Generic.Strong */ +#djDebug .syntax .gu { color: #ffffff; font-weight: bold } /* Generic.Subheading */ +#djDebug .syntax .gt { color: #ffffff } /* Generic.Traceback */ +#djDebug .syntax .kc { color: #fb660a; font-weight: bold } /* Keyword.Constant */ +#djDebug .syntax .kd { color: #fb660a; font-weight: bold } /* Keyword.Declaration */ +#djDebug .syntax .kp { color: #fb660a } /* Keyword.Pseudo */ +#djDebug .syntax .kr { color: #fb660a; font-weight: bold } /* Keyword.Reserved */ +#djDebug .syntax .kt { color: #cdcaa9; font-weight: bold } /* Keyword.Type */ +#djDebug .syntax .ld { color: #ffffff } /* Literal.Date */ +#djDebug .syntax .m { color: #0086f7; font-weight: bold } /* Literal.Number */ +#djDebug .syntax .s { color: #0086d2 } /* Literal.String */ +#djDebug .syntax .na { color: #ff0086; font-weight: bold } /* Name.Attribute */ +#djDebug .syntax .nb { color: #ffffff } /* Name.Builtin */ +#djDebug .syntax .nc { color: #ffffff } /* Name.Class */ +#djDebug .syntax .no { color: #0086d2 } /* Name.Constant */ +#djDebug .syntax .nd { color: #ffffff } /* Name.Decorator */ +#djDebug .syntax .ni { color: #ffffff } /* Name.Entity */ +#djDebug .syntax .ne { color: #ffffff } /* Name.Exception */ +#djDebug .syntax .nf { color: #ff0086; font-weight: bold } /* Name.Function */ +#djDebug .syntax .nl { color: #ffffff } /* Name.Label */ +#djDebug .syntax .nn { color: #ffffff } /* Name.Namespace */ +#djDebug .syntax .nx { color: #ffffff } /* Name.Other */ +#djDebug .syntax .py { color: #ffffff } /* Name.Property */ +#djDebug .syntax .nt { color: #fb660a; font-weight: bold } /* Name.Tag */ +#djDebug .syntax .nv { color: #fb660a } /* Name.Variable */ +#djDebug .syntax .ow { color: #ffffff } /* Operator.Word */ +#djDebug .syntax .w { color: #888888 } /* Text.Whitespace */ +#djDebug .syntax .mf { color: #0086f7; font-weight: bold } /* Literal.Number.Float */ +#djDebug .syntax .mh { color: #0086f7; font-weight: bold } /* Literal.Number.Hex */ +#djDebug .syntax .mi { color: #0086f7; font-weight: bold } /* Literal.Number.Integer */ +#djDebug .syntax .mo { color: #0086f7; font-weight: bold } /* Literal.Number.Oct */ +#djDebug .syntax .sb { color: #0086d2 } /* Literal.String.Backtick */ +#djDebug .syntax .sc { color: #0086d2 } /* Literal.String.Char */ +#djDebug .syntax .sd { color: #0086d2 } /* Literal.String.Doc */ +#djDebug .syntax .s2 { color: #0086d2 } /* Literal.String.Double */ +#djDebug .syntax .se { color: #0086d2 } /* Literal.String.Escape */ +#djDebug .syntax .sh { color: #0086d2 } /* Literal.String.Heredoc */ +#djDebug .syntax .si { color: #0086d2 } /* Literal.String.Interpol */ +#djDebug .syntax .sx { color: #0086d2 } /* Literal.String.Other */ +#djDebug .syntax .sr { color: #0086d2 } /* Literal.String.Regex */ +#djDebug .syntax .s1 { color: #0086d2 } /* Literal.String.Single */ +#djDebug .syntax .ss { color: #0086d2 } /* Literal.String.Symbol */ +#djDebug .syntax .bp { color: #ffffff } /* Name.Builtin.Pseudo */ +#djDebug .syntax .vc { color: #fb660a } /* Name.Variable.Class */ +#djDebug .syntax .vg { color: #fb660a } /* Name.Variable.Global */ +#djDebug .syntax .vi { color: #fb660a } /* Name.Variable.Instance */ +#djDebug .syntax .il { color: #0086f7; font-weight: bold } /* Literal.Number.Integer.Long */ diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index b99709f..e4e3c02 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -72,7 +72,7 @@ def reformat_sql(sql): from pygments import highlight from pygments.lexers import SqlLexer from pygments.formatters import HtmlFormatter - sql = highlight(sql, SqlLexer(), HtmlFormatter(noclasses=True)) + sql = highlight(sql, SqlLexer(), HtmlFormatter()) except ImportError: pass return sql diff --git a/debug_toolbar/templates/debug_toolbar/panels/sql.html b/debug_toolbar/templates/debug_toolbar/panels/sql.html index 4663047..0a8a6e0 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/sql.html +++ b/debug_toolbar/templates/debug_toolbar/panels/sql.html @@ -12,8 +12,8 @@
{% endfor %} - \ No newline at end of file + -- cgit v1.2.3 From 159e690ff3d07c8821332942ae722bdf0bdf5208 Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Tue, 23 Sep 2008 21:06:39 -0700 Subject: Add catch for non JSON serializable objects and don't show the EXPLAIN link for these. --- debug_toolbar/panels/sql.py | 7 ++++++- debug_toolbar/templates/debug_toolbar/panels/sql.html | 6 +++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index e4e3c02..9223cb7 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -16,12 +16,17 @@ class DatabaseStatTracker(util.CursorDebugWrapper): return self.cursor.execute(sql, params) finally: stop = time.time() + _params = None + try: + _params = simplejson.dumps(params) + except TypeError: + pass # object not JSON serializable # We keep `sql` to maintain backwards compatibility self.db.queries.append({ 'sql': self.db.ops.last_executed_query(self.cursor, sql, params), 'time': stop - start, 'raw_sql': sql, - 'params': simplejson.dumps(params), + 'params': _params }) util.CursorDebugWrapper = DatabaseStatTracker diff --git a/debug_toolbar/templates/debug_toolbar/panels/sql.html b/debug_toolbar/templates/debug_toolbar/panels/sql.html index 0a8a6e0..052b36a 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/sql.html +++ b/debug_toolbar/templates/debug_toolbar/panels/sql.html @@ -11,7 +11,11 @@ {% for query in queries %}
{% endfor %} -- cgit v1.2.3 From 39ceacf7c90a984efe21d3d67d30767ffcb97497 Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Tue, 23 Sep 2008 21:20:09 -0700 Subject: Updating pygment css to match Django colors and remove classes not used. --- debug_toolbar/media/toolbar.css | 68 +++++------------------------------------ 1 file changed, 7 insertions(+), 61 deletions(-) diff --git a/debug_toolbar/media/toolbar.css b/debug_toolbar/media/toolbar.css index b1fae96..43ac588 100644 --- a/debug_toolbar/media/toolbar.css +++ b/debug_toolbar/media/toolbar.css @@ -126,71 +126,17 @@ #djDebug .row2 td { background: #356042; } -#djDebug .syntax { background: #111111; color: #ffffff } -#djDebug .syntax .c { color: #008800; font-style: italic; background-color: #0f140f } /* Comment */ +#djDebug .syntax { color: #ffffff } #djDebug .syntax .err { color: #ffffff } /* Error */ #djDebug .syntax .g { color: #ffffff } /* Generic */ -#djDebug .syntax .k { color: #fb660a; font-weight: bold } /* Keyword */ -#djDebug .syntax .l { color: #ffffff } /* Literal */ -#djDebug .syntax .n { color: #ffffff } /* Name */ +#djDebug .syntax .k { color: #F7C757; font-weight: bold } /* Keyword */ #djDebug .syntax .o { color: #ffffff } /* Operator */ +#djDebug .syntax .n { color: #ffffff } /* Name */ +#djDebug .syntax .mi { color: #92ef3f; font-weight: bold } /* Literal.Number.Integer */ +#djDebug .syntax .l { color: #ffffff } /* Literal */ #djDebug .syntax .x { color: #ffffff } /* Other */ #djDebug .syntax .p { color: #ffffff } /* Punctuation */ -#djDebug .syntax .cm { color: #008800; font-style: italic; background-color: #0f140f } /* Comment.Multiline */ -#djDebug .syntax .cp { color: #ff0007; font-weight: bold; font-style: italic; background-color: #0f140f } /* Comment.Preproc */ -#djDebug .syntax .c1 { color: #008800; font-style: italic; background-color: #0f140f } /* Comment.Single */ -#djDebug .syntax .cs { color: #008800; font-style: italic; background-color: #0f140f } /* Comment.Special */ -#djDebug .syntax .gd { color: #ffffff } /* Generic.Deleted */ -#djDebug .syntax .ge { color: #ffffff } /* Generic.Emph */ -#djDebug .syntax .gr { color: #ffffff } /* Generic.Error */ -#djDebug .syntax .gh { color: #ffffff; font-weight: bold } /* Generic.Heading */ -#djDebug .syntax .gi { color: #ffffff } /* Generic.Inserted */ -#djDebug .syntax .go { color: #444444; background-color: #222222 } /* Generic.Output */ -#djDebug .syntax .gp { color: #ffffff } /* Generic.Prompt */ -#djDebug .syntax .gs { color: #ffffff } /* Generic.Strong */ -#djDebug .syntax .gu { color: #ffffff; font-weight: bold } /* Generic.Subheading */ -#djDebug .syntax .gt { color: #ffffff } /* Generic.Traceback */ -#djDebug .syntax .kc { color: #fb660a; font-weight: bold } /* Keyword.Constant */ -#djDebug .syntax .kd { color: #fb660a; font-weight: bold } /* Keyword.Declaration */ -#djDebug .syntax .kp { color: #fb660a } /* Keyword.Pseudo */ -#djDebug .syntax .kr { color: #fb660a; font-weight: bold } /* Keyword.Reserved */ -#djDebug .syntax .kt { color: #cdcaa9; font-weight: bold } /* Keyword.Type */ -#djDebug .syntax .ld { color: #ffffff } /* Literal.Date */ -#djDebug .syntax .m { color: #0086f7; font-weight: bold } /* Literal.Number */ +#djDebug .syntax .m { color: #92ef3f; font-weight: bold } /* Literal.Number */ #djDebug .syntax .s { color: #0086d2 } /* Literal.String */ -#djDebug .syntax .na { color: #ff0086; font-weight: bold } /* Name.Attribute */ -#djDebug .syntax .nb { color: #ffffff } /* Name.Builtin */ -#djDebug .syntax .nc { color: #ffffff } /* Name.Class */ -#djDebug .syntax .no { color: #0086d2 } /* Name.Constant */ -#djDebug .syntax .nd { color: #ffffff } /* Name.Decorator */ -#djDebug .syntax .ni { color: #ffffff } /* Name.Entity */ -#djDebug .syntax .ne { color: #ffffff } /* Name.Exception */ -#djDebug .syntax .nf { color: #ff0086; font-weight: bold } /* Name.Function */ -#djDebug .syntax .nl { color: #ffffff } /* Name.Label */ -#djDebug .syntax .nn { color: #ffffff } /* Name.Namespace */ -#djDebug .syntax .nx { color: #ffffff } /* Name.Other */ -#djDebug .syntax .py { color: #ffffff } /* Name.Property */ -#djDebug .syntax .nt { color: #fb660a; font-weight: bold } /* Name.Tag */ -#djDebug .syntax .nv { color: #fb660a } /* Name.Variable */ -#djDebug .syntax .ow { color: #ffffff } /* Operator.Word */ #djDebug .syntax .w { color: #888888 } /* Text.Whitespace */ -#djDebug .syntax .mf { color: #0086f7; font-weight: bold } /* Literal.Number.Float */ -#djDebug .syntax .mh { color: #0086f7; font-weight: bold } /* Literal.Number.Hex */ -#djDebug .syntax .mi { color: #0086f7; font-weight: bold } /* Literal.Number.Integer */ -#djDebug .syntax .mo { color: #0086f7; font-weight: bold } /* Literal.Number.Oct */ -#djDebug .syntax .sb { color: #0086d2 } /* Literal.String.Backtick */ -#djDebug .syntax .sc { color: #0086d2 } /* Literal.String.Char */ -#djDebug .syntax .sd { color: #0086d2 } /* Literal.String.Doc */ -#djDebug .syntax .s2 { color: #0086d2 } /* Literal.String.Double */ -#djDebug .syntax .se { color: #0086d2 } /* Literal.String.Escape */ -#djDebug .syntax .sh { color: #0086d2 } /* Literal.String.Heredoc */ -#djDebug .syntax .si { color: #0086d2 } /* Literal.String.Interpol */ -#djDebug .syntax .sx { color: #0086d2 } /* Literal.String.Other */ -#djDebug .syntax .sr { color: #0086d2 } /* Literal.String.Regex */ -#djDebug .syntax .s1 { color: #0086d2 } /* Literal.String.Single */ -#djDebug .syntax .ss { color: #0086d2 } /* Literal.String.Symbol */ -#djDebug .syntax .bp { color: #ffffff } /* Name.Builtin.Pseudo */ -#djDebug .syntax .vc { color: #fb660a } /* Name.Variable.Class */ -#djDebug .syntax .vg { color: #fb660a } /* Name.Variable.Global */ -#djDebug .syntax .vi { color: #fb660a } /* Name.Variable.Instance */ -#djDebug .syntax .il { color: #0086f7; font-weight: bold } /* Literal.Number.Integer.Long */ +#djDebug .syntax .il { color: #92ef3f; font-weight: bold } /* Literal.Number.Integer.Long */ -- cgit v1.2.3 From d74431411b5c390379bcac89a60628a26365d8c9 Mon Sep 17 00:00:00 2001 From: Jannis Leidel Date: Wed, 24 Sep 2008 12:40:02 +0200 Subject: Added context processors to TemplateDebugPanel --- debug_toolbar/panels/template.py | 7 +++++++ .../templates/debug_toolbar/panels/templates.html | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template.py index eb20079..9cab618 100644 --- a/debug_toolbar/panels/template.py +++ b/debug_toolbar/panels/template.py @@ -4,6 +4,7 @@ from django.core.signals import request_started from django.dispatch import Signal from django.template.loader import render_to_string from django.test.signals import template_rendered +from django.template.context import get_standard_processors from debug_toolbar.panels import DebugPanel # Code taken and adapted from Simon Willison and Django Snippets: @@ -44,6 +45,11 @@ class TemplateDebugPanel(DebugPanel): def url(self): return '' + def process_request(self, request): + self.context_processors = dict( + [("%s.%s" % (k.__module__, k.__name__), pformat(k(request))) for k in get_standard_processors()] + ) + def content(self): template_context = [] for i, d in enumerate(self.templates): @@ -65,5 +71,6 @@ class TemplateDebugPanel(DebugPanel): context = { 'templates': template_context, 'template_dirs': settings.TEMPLATE_DIRS, + 'context_processors': self.context_processors, } return render_to_string('debug_toolbar/panels/templates.html', context) diff --git a/debug_toolbar/templates/debug_toolbar/panels/templates.html b/debug_toolbar/templates/debug_toolbar/panels/templates.html index 575d507..e878be2 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/templates.html +++ b/debug_toolbar/templates/debug_toolbar/panels/templates.html @@ -23,3 +23,17 @@ {% else %} None {% endif %} +{% if context_processors %} +
+
+{% else %} + None +{% endif %} -- cgit v1.2.3 From 85d879803c88aa036934d36977a10b5d28b70aaa Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Wed, 24 Sep 2008 16:23:01 -0700 Subject: Adding a SHA-1 hash to the parameters passed to get the EXPLAIN query to avoid any sort of tampering of the SQL or parameters. --- debug_toolbar/panels/sql.py | 7 +++++-- debug_toolbar/templates/debug_toolbar/panels/sql.html | 2 +- debug_toolbar/views.py | 13 ++++++++++--- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index 9223cb7..22d65a7 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -1,9 +1,11 @@ import time from debug_toolbar.panels import DebugPanel +from django.conf import settings from django.db import connection from django.db.backends import util from django.template.loader import render_to_string from django.utils import simplejson +from django.utils.hashcompat import sha_constructor class DatabaseStatTracker(util.CursorDebugWrapper): """ @@ -26,7 +28,8 @@ class DatabaseStatTracker(util.CursorDebugWrapper): 'sql': self.db.ops.last_executed_query(self.cursor, sql, params), 'time': stop - start, 'raw_sql': sql, - 'params': _params + 'params': _params, + 'hash': sha_constructor(settings.SECRET_KEY + sql + _params).hexdigest(), }) util.CursorDebugWrapper = DatabaseStatTracker @@ -37,7 +40,7 @@ class SQLDebugPanel(DebugPanel): """ name = 'SQL' has_content = True - + def __init__(self): self._offset = len(connection.queries) self._sql_time = 0 diff --git a/debug_toolbar/templates/debug_toolbar/panels/sql.html b/debug_toolbar/templates/debug_toolbar/panels/sql.html index 052b36a..e218f22 100644 --- a/debug_toolbar/templates/debug_toolbar/panels/sql.html +++ b/debug_toolbar/templates/debug_toolbar/panels/sql.html @@ -13,7 +13,7 @@
diff --git a/debug_toolbar/views.py b/debug_toolbar/views.py index 97739e6..b67a70b 100644 --- a/debug_toolbar/views.py +++ b/debug_toolbar/views.py @@ -8,8 +8,10 @@ import os import django.views.static from django.conf import settings from django.db import connection +from django.http import HttpResponse from django.shortcuts import render_to_response from django.utils import simplejson +from django.utils.hashcompat import sha_constructor def debug_media(request, path): root = getattr(settings, 'DEBUG_TOOLBAR_MEDIA_ROOT', None) @@ -21,16 +23,21 @@ def debug_media(request, path): def sql_explain(request): """ Returns the output of the SQL EXPLAIN on the given query. - + Expected GET variables: - sql: urlencoded sql with position arguments + sql: urlencoded sql with positional arguments params: JSON encoded parameter values time: time for SQL to execute passed in from toolbar just for redisplay + hash: the hash of (secret + sql + params) for tamper checking """ from debug_toolbar.panels.sql import reformat_sql sql = request.GET.get('sql', '') + params = request.GET.get('params', '') + hash = sha_constructor(settings.SECRET_KEY + sql + params).hexdigest() + if hash != request.GET.get('hash', ''): + return HttpResponse('
') # SQL Tampering alert if sql.lower().startswith('select'): - params = simplejson.loads(request.GET.get('params', '')) + params = simplejson.loads(params) cursor = connection.cursor() cursor.execute("EXPLAIN %s" % (sql,), params) headers = [d[0] for d in cursor.description] -- cgit v1.2.3 From c70df302e1564a7f7fe7883d3e042419ece1d9e6 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 27 Sep 2008 15:50:47 -0400 Subject: added logger panel --- debug_toolbar/media/toolbar.css | 2 +- debug_toolbar/panels/logger.py | 73 ++++++++++++++++++++++ .../templates/debug_toolbar/panels/logger.html | 26 ++++++++ debug_toolbar/toolbar/loader.py | 1 + 4 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 debug_toolbar/panels/logger.py create mode 100644 debug_toolbar/templates/debug_toolbar/panels/logger.html diff --git a/debug_toolbar/media/toolbar.css b/debug_toolbar/media/toolbar.css index 43ac588..bad28c5 100644 --- a/debug_toolbar/media/toolbar.css +++ b/debug_toolbar/media/toolbar.css @@ -22,7 +22,7 @@ margin: 0; padding: 0; line-height: 30px; - padding: 8px 10px 9px; + padding: 8px 9px 9px; position: relative; width: auto; } diff --git a/debug_toolbar/panels/logger.py b/debug_toolbar/panels/logger.py new file mode 100644 index 0000000..e3fd21e --- /dev/null +++ b/debug_toolbar/panels/logger.py @@ -0,0 +1,73 @@ +import datetime +import logging + +try: + import threading +except ImportError: + threading = None + +from django.template.loader import render_to_string + +from debug_toolbar.panels import DebugPanel + +class ThreadTrackingHandler(logging.Handler): + def __init__(self): + if threading is None: + raise NotImplementedError("threading module is not available, \ + the logging panel cannot be used without it") + logging.Handler.__init__(self) + self.records = {} # a dictionary that maps threads to log records + + def emit(self, record): + self.get_records().append(record) + + def get_records(self, thread=None): + """ + Returns a list of records for the provided thread, of if none is provided, + returns a list for the current thread. + """ + if thread is None: + thread = threading.currentThread() + if thread not in self.records: + self.records[thread] = [] + return self.records[thread] + + def clear_records(self, thread=None): + if thread is None: + thread = threading.currentThread() + if thread in self.records: + del self.records[thread] + +handler = ThreadTrackingHandler() +logging.root.setLevel(logging.NOTSET) +logging.root.addHandler(handler) + +class LoggingPanel(DebugPanel): + name = 'Logging' + has_content = True + + def process_request(self, request): + handler.clear_records() + + def get_and_delete(self): + records = handler.get_records() + handler.clear_records() + return records + + def title(self): + return "Logging (%s message%s)" % (len(handler.get_records()), (len(handler.get_records()) == 1) and '' or 's') + + def url(self): + return '' + + def content(self): + records = [] + for record in self.get_and_delete(): + records.append({ + 'message': record.getMessage(), + 'time': datetime.datetime.fromtimestamp(record.created), + 'level': record.levelname, + 'file': record.pathname, + 'line': record.lineno, + }) + return render_to_string('debug_toolbar/panels/logger.html', {'records': records}) diff --git a/debug_toolbar/templates/debug_toolbar/panels/logger.html b/debug_toolbar/templates/debug_toolbar/panels/logger.html new file mode 100644 index 0000000..93443be --- /dev/null +++ b/debug_toolbar/templates/debug_toolbar/panels/logger.html @@ -0,0 +1,26 @@ +
+{% if records %} +
| Level | +Time | +Message | +Location | +
|---|---|---|---|
| {{ record.level }} | +{{ record.time|date:"h:i:s m/d/Y" }} | +{{ record.message }} | +{{ record.file }}:{{ record.line }} | +
+{% else %} +
No messages logged.
+{% endif %} + diff --git a/debug_toolbar/toolbar/loader.py b/debug_toolbar/toolbar/loader.py index 0ac9096..e2c9793 100644 --- a/debug_toolbar/toolbar/loader.py +++ b/debug_toolbar/toolbar/loader.py @@ -17,6 +17,7 @@ class DebugToolbar(object): 'debug_toolbar.panels.sql.SQLDebugPanel', 'debug_toolbar.panels.cache.CacheDebugPanel', 'debug_toolbar.panels.template.TemplateDebugPanel', + 'debug_toolbar.panels.logger.LoggingPanel', ) self.load_panels() -- cgit v1.2.3 From 76dbd5b1d2cf1a9ab1a6384a016e5628444b0a5c Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Sat, 27 Sep 2008 22:23:03 -0700 Subject: Adding info about the Logging panel to the README --- README.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.rst b/README.rst index c5e4c5f..7c0c8f3 100644 --- a/README.rst +++ b/README.rst @@ -15,6 +15,7 @@ Currently, the following panels have been written and are working: - SQL queries including time to execute and links to EXPLAIN each query - Cache stats - Templates and context used, and their template paths +- Logging output via Python's built-in logging module If you have ideas for other panels please let us know. @@ -58,6 +59,7 @@ Installation 'debug_toolbar.panels.sql.SQLDebugPanel', 'debug_toolbar.panels.cache.CacheDebugPanel', 'debug_toolbar.panels.template.TemplateDebugPanel', + 'debug_toolbar.panels.logger.LoggingPanel', ) You can change the ordering of this tuple to customize the order of the -- cgit v1.2.3 From ce8c68b79c2de4abde01b29b1c73754ce4deb981 Mon Sep 17 00:00:00 2001 From: Rob Hudson Date: Sun, 28 Sep 2008 08:36:17 -0700 Subject: Updated to fail nicely when DEBUG=False. --- debug_toolbar/middleware.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/debug_toolbar/middleware.py b/debug_toolbar/middleware.py index 0a202e2..6d2391c 100644 --- a/debug_toolbar/middleware.py +++ b/debug_toolbar/middleware.py @@ -50,10 +50,13 @@ class DebugToolbarMiddleware(object): return None def process_view(self, request, view_func, view_args, view_kwargs): - for panel in self.debug_toolbar.panels: - panel.process_view(request, view_func, view_args, view_kwargs) + if self.debug_toolbar: + for panel in self.debug_toolbar.panels: + panel.process_view(request, view_func, view_args, view_kwargs) def process_response(self, request, response): + if not self.debug_toolbar: + return response if response.status_code != 200: return response for panel in self.debug_toolbar.panels: -- cgit v1.2.3