From a7a20b41ef3a7692eb3797707f68368eae08ef06 Mon Sep 17 00:00:00 2001
From: Max Klymyshyn
Date: Mon, 25 Apr 2011 22:06:10 +0300
Subject: [PATCH 01/10] Added StateDebugPanel with examples - debug how much
and what objects was created/updated/deleted
---
README.rst | 2 +
.../media/debug_toolbar/css/toolbar.css | 68 +++++++
.../media/debug_toolbar/css/toolbar.min.css | 2 +-
debug_toolbar/panels/state.py | 168 ++++++++++++++++++
.../templates/debug_toolbar/panels/state.html | 72 ++++++++
debug_toolbar/toolbar/loader.py | 1 +
debug_toolbar/views.py | 2 +
example/example.db | Bin 55296 -> 40960 bytes
example/models.py | 8 +
example/settings.py | 5 +
example/urls.py | 2 +-
example/views.py | 33 ++++
12 files changed, 361 insertions(+), 2 deletions(-)
create mode 100644 debug_toolbar/panels/state.py
create mode 100644 debug_toolbar/templates/debug_toolbar/panels/state.html
create mode 100644 example/models.py
create mode 100644 example/views.py
diff --git a/README.rst b/README.rst
index d90180e7b..122059944 100644
--- a/README.rst
+++ b/README.rst
@@ -17,6 +17,7 @@ Currently, the following panels have been written and are working:
- SQL queries including time to execute and links to EXPLAIN each query
- List of signals, their args and receivers
- Logging output via Python's built-in logging module
+- State of available objects in the project - how much created/udpated/deleted
There is also one Django management command currently:
@@ -85,6 +86,7 @@ The debug toolbar has two settings that can be set in `settings.py`:
'debug_toolbar.panels.sql.SQLDebugPanel',
'debug_toolbar.panels.signals.SignalDebugPanel',
'debug_toolbar.panels.logger.LoggingPanel',
+ 'debug_toolbar.panels.state.StateDebugPanel',
)
You can change the ordering of this tuple to customize the order of the
diff --git a/debug_toolbar/media/debug_toolbar/css/toolbar.css b/debug_toolbar/media/debug_toolbar/css/toolbar.css
index 223869deb..28ffc7804 100644
--- a/debug_toolbar/media/debug_toolbar/css/toolbar.css
+++ b/debug_toolbar/media/debug_toolbar/css/toolbar.css
@@ -394,3 +394,71 @@
#djDebug .highlight .nv { color:#333 } /* Name.Variable */
#djDebug .highlight .s2 { color:#333 } /* Literal.String.Double */
#djDebug .highlight .cp { color:#333 } /* Comment.Preproc */
+
+
+/**
+ * State panel style
+*/
+#djDebug .created,
+#djDebug tr.created-obj {
+ background-color:#83F7A8;
+}
+
+#djDebug .updated,
+#djDebug tr.updated-obj {
+ background-color:#82E3F7;
+}
+#djDebug .deleted,
+#djDebug tr.deleted-obj {
+ background-color:#F79A83;
+}
+
+#djDebug span.deleted,
+#djDebug span.updated,
+#djDebug span.created {
+ display:inline;
+ display:inline-block;
+ padding:3px;
+}
+
+#djDebug .djDebug-state-summary {
+ overflow:hidden;
+ width:100%;
+}
+#djDebug .djDebug-state-summary legend {
+ font-size:1.3em;
+ padding-top:1em;
+}
+
+#djDebug .djDebug-state-summary dl {
+ clear:both;
+ margin-top:15px;
+}
+#djDebug dt.deleted {
+ float:left;
+}
+#djDebug .panelContent .djDebug-state-summary dt,
+#djDebug .panelContent .djDebug-state-summary dd {
+ margin:0; padding:0;
+ float:left;
+}
+
+#djDebug .panelContent .djDebug-state-summary dt {
+ font-size:1.2em;
+ padding-left:0.3em;
+ padding-right:0.3em;
+}
+
+#djDebug .panelContent .djDebug-state-summary dd {
+ font-size:1.4em;
+ font-weight:bold;
+ padding-left:10px;
+ padding-right:20px;
+ line-height:1.2em;
+}
+
+#djDebug table th.io-cell,
+#djDebug table td.io-cell {
+ border-top:1px solid #fff;
+ text-align:center;
+}
\ No newline at end of file
diff --git a/debug_toolbar/media/debug_toolbar/css/toolbar.min.css b/debug_toolbar/media/debug_toolbar/css/toolbar.min.css
index 2f2d7db0a..e3e24c629 100644
--- a/debug_toolbar/media/debug_toolbar/css/toolbar.min.css
+++ b/debug_toolbar/media/debug_toolbar/css/toolbar.min.css
@@ -1 +1 @@
-#djDebug{color:#000;background:#FFF;}#djDebug,#djDebug div,#djDebug span,#djDebug applet,#djDebug object,#djDebug iframe,#djDebug h1,#djDebug h2,#djDebug h3,#djDebug h4,#djDebug h5,#djDebug h6,#djDebug p,#djDebug blockquote,#djDebug pre,#djDebug a,#djDebug abbr,#djDebug acronym,#djDebug address,#djDebug big,#djDebug cite,#djDebug code,#djDebug del,#djDebug dfn,#djDebug em,#djDebug font,#djDebug img,#djDebug ins,#djDebug kbd,#djDebug q,#djDebug s,#djDebug samp,#djDebug small,#djDebug strike,#djDebug strong,#djDebug sub,#djDebug sup,#djDebug tt,#djDebug var,#djDebug b,#djDebug u,#djDebug i,#djDebug center,#djDebug dl,#djDebug dt,#djDebug dd,#djDebug ol,#djDebug ul,#djDebug li,#djDebug fieldset,#djDebug form,#djDebug label,#djDebug legend,#djDebug table,#djDebug caption,#djDebug tbody,#djDebug tfoot,#djDebug thead,#djDebug tr,#djDebug th,#djDebug td{margin:0;padding:0;border:0;outline:0;font-size:12px;line-height:1.5em;color:#000;vertical-align:baseline;background:transparent;font-family:sans-serif;text-align:left;}#djDebug #djDebugToolbar{background:#111;width:200px;z-index:100000000;position:fixed;top:0;bottom:0;right:0;opacity:.9;}#djDebug #djDebugToolbar small{color:#999;}#djDebug #djDebugToolbar ul{margin:0;padding:0;list-style:none;}#djDebug #djDebugToolbar li{border-bottom:1px solid #222;color:#fff;display:block;font-weight:bold;float:none;margin:0;padding:0;position:relative;width:auto;}#djDebug #djDebugToolbar li>a,#djDebug #djDebugToolbar li>div.contentless{font-weight:normal;font-style:normal;text-decoration:none;display:block;font-size:16px;padding:10px 10px 5px 25px;color:#fff;}#djDebug #djDebugToolbar li a:hover{color:#111;background-color:#ffc;}#djDebug #djDebugToolbar li.active{background-image:url(../img/indicator.png);background-repeat:no-repeat;background-position:left center;background-color:#333;padding-left:10px;}#djDebug #djDebugToolbar li.active a:hover{color:#b36a60;background-color:transparent;}#djDebug #djDebugToolbar li small{font-size:12px;color:#999;font-style:normal;text-decoration:none;font-variant:small-caps;}#djDebug #djDebugToolbarHandle{position:fixed;background:#fff;border:1px solid #111;top:30px;right:0;z-index:100000000;opacity:.75;}#djDebug a#djShowToolBarButton{display:block;height:75px;width:30px;border-right:none;border-bottom:4px solid #fff;border-top:4px solid #fff;border-left:4px solid #fff;color:#fff;font-size:10px;font-weight:bold;text-decoration:none;text-align:center;text-indent:-999999px;background:#000 url(../img/djdt_vertical.png) no-repeat left center;opacity:.5;}#djDebug a#djShowToolBarButton:hover{background-color:#111;padding-right:6px;border-top-color:#FFE761;border-left-color:#FFE761;border-bottom-color:#FFE761;opacity:1.0;}#djDebug code{display:block;font-family:Consolas,Monaco,"Bitstream Vera Sans Mono","Lucida Console",monospace;white-space:pre;overflow:auto;}#djDebug tr.djDebugOdd{background-color:#f5f5f5;}#djDebug .panelContent{display:none;position:fixed;margin:0;top:0;right:200px;bottom:0;left:0;background-color:#eee;color:#666;z-index:100000000;}#djDebug .panelContent>div{border-bottom:1px solid #ddd;}#djDebug .djDebugPanelTitle{position:absolute;background-color:#ffc;color:#666;padding-left:20px;top:0;right:0;left:0;height:50px;}#djDebug .djDebugPanelTitle code{display:inline;font-size:inherit;}#djDebug .djDebugPanelContent{position:absolute;top:50px;right:0;bottom:0;left:0;height:auto;padding:0 0 0 20px;}#djDebug .djDebugPanelContent .scroll{height:100%;overflow:auto;display:block;padding:0 10px 0 0;}#djDebug h3{font-size:24px;font-weight:normal;line-height:50px;}#djDebug h4{font-size:20px;font-weight:bold;margin-top:.8em;}#djDebug .panelContent table{border:1px solid #ccc;border-collapse:collapse;width:100%;background-color:#fff;display:block;margin-top:.8em;overflow:auto;}#djDebug .panelContent tbody td,#djDebug .panelContent tbody th{vertical-align:top;padding:2px 3px;}#djDebug .panelContent thead th{padding:1px 6px 1px 3px;text-align:left;font-weight:bold;font-size:14px;}#djDebug .panelContent tbody th{width:12em;text-align:right;color:#666;padding-right:.5em;}#djDebug .djTemplateHideContextDiv{background-color:#fff;}#djDebug .panelContent .djDebugClose{text-indent:-9999999px;display:block;position:absolute;top:4px;right:15px;height:40px;width:40px;background:url(../img/close.png) no-repeat center center;}#djDebug .panelContent .djDebugClose:hover{background-image:url(../img/close_hover.png);}#djDebug .panelContent .djDebugClose.djDebugBack{background-image:url(../img/back.png);}#djDebug .panelContent .djDebugClose.djDebugBack:hover{background-image:url(../img/back_hover.png);}#djDebug .panelContent dt,#djDebug .panelContent dd{display:block;}#djDebug .panelContent dt{margin-top:.75em;}#djDebug .panelContent dd{margin-left:10px;}#djDebug a.toggleTemplate{padding:4px;background-color:#bbb;-moz-border-radius:3px;-webkit-border-radius:3px;}#djDebug a.toggleTemplate:hover{padding:4px;background-color:#444;color:#ffe761;-moz-border-radius:3px;-webkit-border-radius:3px;}#djDebug a.djTemplateShowContext,#djDebug a.djTemplateShowContext span.toggleArrow{color:#999;}#djDebug a.djTemplateShowContext:hover,#djDebug a.djTemplateShowContext:hover span.toggleArrow{color:#000;cursor:pointer;}#djDebug .djDebugSqlWrap{position:relative;}#djDebug .djDebugSql{z-index:100000002;}#djDebug .djSQLHideStacktraceDiv tbody th{text-align:left;}#djDebug .djSqlExplain td{white-space:pre;}#djDebug span.djDebugLineChart{background-color:#777;height:3px;position:absolute;bottom:0;top:0;left:0;display:block;z-index:1000000001;}#djDebug span.djDebugLineChartWarning{background-color:#900;}#djDebug .highlight{color:#000;}#djDebug .highlight .err{color:#000;}#djDebug .highlight .g{color:#000;}#djDebug .highlight .k{color:#000;font-weight:bold;}#djDebug .highlight .o{color:#000;}#djDebug .highlight .n{color:#000;}#djDebug .highlight .mi{color:#000;font-weight:bold;}#djDebug .highlight .l{color:#000;}#djDebug .highlight .x{color:#000;}#djDebug .highlight .p{color:#000;}#djDebug .highlight .m{color:#000;font-weight:bold;}#djDebug .highlight .s{color:#333;}#djDebug .highlight .w{color:#888;}#djDebug .highlight .il{color:#000;font-weight:bold;}#djDebug .highlight .na{color:#333;}#djDebug .highlight .nt{color:#000;font-weight:bold;}#djDebug .highlight .nv{color:#333;}#djDebug .highlight .s2{color:#333;}#djDebug .highlight .cp{color:#333;}
\ No newline at end of file
+#djDebug{color:#000;background:#FFF}#djDebug,#djDebug div,#djDebug span,#djDebug applet,#djDebug object,#djDebug iframe,#djDebug h1,#djDebug h2,#djDebug h3,#djDebug h4,#djDebug h5,#djDebug h6,#djDebug p,#djDebug blockquote,#djDebug pre,#djDebug a,#djDebug abbr,#djDebug acronym,#djDebug address,#djDebug big,#djDebug cite,#djDebug code,#djDebug del,#djDebug dfn,#djDebug em,#djDebug font,#djDebug img,#djDebug ins,#djDebug kbd,#djDebug q,#djDebug s,#djDebug samp,#djDebug small,#djDebug strike,#djDebug strong,#djDebug sub,#djDebug sup,#djDebug tt,#djDebug var,#djDebug b,#djDebug u,#djDebug i,#djDebug center,#djDebug dl,#djDebug dt,#djDebug dd,#djDebug ol,#djDebug ul,#djDebug li,#djDebug fieldset,#djDebug form,#djDebug label,#djDebug legend,#djDebug table,#djDebug caption,#djDebug tbody,#djDebug tfoot,#djDebug thead,#djDebug tr,#djDebug th,#djDebug td{margin:0;padding:0;border:0;outline:0;font-size:12px;line-height:1.5em;color:#000;vertical-align:baseline;background:transparent;font-family:sans-serif;text-align:left}#djDebug #djDebugToolbar{background:#111;width:200px;z-index:100000000;position:fixed;top:0;bottom:0;right:0;opacity:.9}#djDebug #djDebugToolbar small{color:#999}#djDebug #djDebugToolbar ul{margin:0;padding:0;list-style:none}#djDebug #djDebugToolbar li{border-bottom:1px solid #222;color:#fff;display:block;font-weight:bold;float:none;margin:0;padding:0;position:relative;width:auto}#djDebug #djDebugToolbar li>a,#djDebug #djDebugToolbar li>div.contentless{font-weight:normal;font-style:normal;text-decoration:none;display:block;font-size:16px;padding:10px 10px 5px 25px;color:#fff}#djDebug #djDebugToolbar li a:hover{color:#111;background-color:#ffc}#djDebug #djDebugToolbar li.active{background-image:url(../img/indicator.png);background-repeat:no-repeat;background-position:left center;background-color:#333;padding-left:10px}#djDebug #djDebugToolbar li.active a:hover{color:#b36a60;background-color:transparent}#djDebug #djDebugToolbar li small{font-size:12px;color:#999;font-style:normal;text-decoration:none;font-variant:small-caps}#djDebug #djDebugToolbarHandle{position:fixed;background:#fff;border:1px solid #111;top:30px;right:0;z-index:100000000;opacity:.75}#djDebug a#djShowToolBarButton{display:block;height:75px;width:30px;border-right:none;border-bottom:4px solid #fff;border-top:4px solid #fff;border-left:4px solid #fff;color:#fff;font-size:10px;font-weight:bold;text-decoration:none;text-align:center;text-indent:-999999px;background:#000 url(../img/djdt_vertical.png) no-repeat left center;opacity:.5}#djDebug a#djShowToolBarButton:hover{background-color:#111;padding-right:6px;border-top-color:#ffe761;border-left-color:#ffe761;border-bottom-color:#ffe761;opacity:1.0}#djDebug code{display:block;font-family:Consolas,Monaco,"Bitstream Vera Sans Mono","Lucida Console",monospace;white-space:pre;overflow:auto}#djDebug tr.djDebugOdd{background-color:#f5f5f5}#djDebug .panelContent{display:none;position:fixed;margin:0;top:0;right:200px;bottom:0;left:0;background-color:#eee;color:#666;z-index:100000000}#djDebug .panelContent>div{border-bottom:1px solid #ddd}#djDebug .djDebugPanelTitle{position:absolute;background-color:#ffc;color:#666;padding-left:20px;top:0;right:0;left:0;height:50px}#djDebug .djDebugPanelTitle code{display:inline;font-size:inherit}#djDebug .djDebugPanelContent{position:absolute;top:50px;right:0;bottom:0;left:0;height:auto;padding:0 0 0 20px}#djDebug .djDebugPanelContent .scroll{height:100%;overflow:auto;display:block;padding:0 10px 0 0}#djDebug h3{font-size:24px;font-weight:normal;line-height:50px}#djDebug h4{font-size:20px;font-weight:bold;margin-top:.8em}#djDebug .panelContent table{border:1px solid #ccc;border-collapse:collapse;width:100%;background-color:#fff;display:block;margin-top:.8em;overflow:auto}#djDebug .panelContent tbody td,#djDebug .panelContent tbody th{vertical-align:top;padding:2px 3px}#djDebug .panelContent thead th{padding:1px 6px 1px 3px;text-align:left;font-weight:bold;font-size:14px}#djDebug .panelContent tbody th{width:12em;text-align:right;color:#666;padding-right:.5em}#djDebug .djTemplateHideContextDiv{background-color:#fff}#djDebug .panelContent .djDebugClose{text-indent:-9999999px;display:block;position:absolute;top:4px;right:15px;height:40px;width:40px;background:url(../img/close.png) no-repeat center center}#djDebug .panelContent .djDebugClose:hover{background-image:url(../img/close_hover.png)}#djDebug .panelContent .djDebugClose.djDebugBack{background-image:url(../img/back.png)}#djDebug .panelContent .djDebugClose.djDebugBack:hover{background-image:url(../img/back_hover.png)}#djDebug .panelContent dt,#djDebug .panelContent dd{display:block}#djDebug .panelContent dt{margin-top:.75em}#djDebug .panelContent dd{margin-left:10px}#djDebug a.toggleTemplate{padding:4px;background-color:#bbb;-moz-border-radius:3px;-webkit-border-radius:3px}#djDebug a.toggleTemplate:hover{padding:4px;background-color:#444;color:#ffe761;-moz-border-radius:3px;-webkit-border-radius:3px}#djDebug a.djTemplateShowContext,#djDebug a.djTemplateShowContext span.toggleArrow{color:#999}#djDebug a.djTemplateShowContext:hover,#djDebug a.djTemplateShowContext:hover span.toggleArrow{color:#000;cursor:pointer}#djDebug .djDebugSqlWrap{position:relative}#djDebug .djDebugSql{z-index:100000002}#djDebug .djSQLHideStacktraceDiv tbody th{text-align:left}#djDebug .djSqlExplain td{white-space:pre}#djDebug span.djDebugLineChart{background-color:#777;height:3px;position:absolute;bottom:0;top:0;left:0;display:block;z-index:1000000001}#djDebug span.djDebugLineChartWarning{background-color:#900}#djDebug .highlight{color:#000}#djDebug .highlight .err{color:#000}#djDebug .highlight .g{color:#000}#djDebug .highlight .k{color:#000;font-weight:bold}#djDebug .highlight .o{color:#000}#djDebug .highlight .n{color:#000}#djDebug .highlight .mi{color:#000;font-weight:bold}#djDebug .highlight .l{color:#000}#djDebug .highlight .x{color:#000}#djDebug .highlight .p{color:#000}#djDebug .highlight .m{color:#000;font-weight:bold}#djDebug .highlight .s{color:#333}#djDebug .highlight .w{color:#888}#djDebug .highlight .il{color:#000;font-weight:bold}#djDebug .highlight .na{color:#333}#djDebug .highlight .nt{color:#000;font-weight:bold}#djDebug .highlight .nv{color:#333}#djDebug .highlight .s2{color:#333}#djDebug .highlight .cp{color:#333}#djDebug .created,#djDebug tr.created-obj{background-color:#83f7a8}#djDebug .updated,#djDebug tr.updated-obj{background-color:#82e3f7}#djDebug .deleted,#djDebug tr.deleted-obj{background-color:#f79a83}#djDebug span.deleted,#djDebug span.updated,#djDebug span.created{display:inline;display:inline-block;padding:3px}#djDebug .djDebug-state-summary{overflow:hidden;width:100%}#djDebug .djDebug-state-summary legend{font-size:1.3em;padding-top:1em}#djDebug .djDebug-state-summary dl{clear:both;margin-top:15px}#djDebug dt.deleted{float:left}#djDebug .panelContent .djDebug-state-summary dt,#djDebug .panelContent .djDebug-state-summary dd{margin:0;padding:0;float:left}#djDebug .panelContent .djDebug-state-summary dt{font-size:1.2em;padding-left:.3em;padding-right:.3em}#djDebug .panelContent .djDebug-state-summary dd{font-size:1.4em;font-weight:bold;padding-left:10px;padding-right:20px;line-height:1.2em}#djDebug table th.io-cell,#djDebug table td.io-cell{border-top:1px solid #fff;text-align:center}
\ No newline at end of file
diff --git a/debug_toolbar/panels/state.py b/debug_toolbar/panels/state.py
new file mode 100644
index 000000000..ded3414a9
--- /dev/null
+++ b/debug_toolbar/panels/state.py
@@ -0,0 +1,168 @@
+import re
+
+from django.db import models
+from django.db.models.signals import post_save, post_delete
+from django.template.loader import render_to_string
+from django.utils.translation import ugettext_lazy as _
+from django.utils.safestring import mark_safe
+
+from debug_toolbar.panels import DebugPanel
+
+
+class StateDebugPanel(DebugPanel):
+ name = "State"
+ has_content = True
+
+ ADD = 1
+ UPDATE = 2
+ DELETE = 3
+
+ objs_created = 0
+ objs_deleted = 0
+ objs_updated = 0
+
+ objects_state = {}
+ prev_objects_state = {}
+
+ log_data = []
+
+ keys = {ADD: 'created', UPDATE: 'updated', DELETE: 'deleted'}
+
+ def nav_title(self):
+ return _("State")
+
+ def nav_subtitle(self):
+ return mark_safe(_("%(created)d created, "\
+ "%(updated)d changed, %(deleted)d deleted") % {
+ 'created': self.objs_created,
+ 'deleted': self.objs_deleted,
+ 'updated': self.objs_updated,
+ })
+
+ def title(self):
+ return _("Objects State")
+
+ def url(self):
+ return ''
+
+ def _track_save(cls, *args, **kwargs):
+ """Method to track every post_save signal and increase amount of
+ create/change action for corresponding object"""
+ is_created = False
+ action = cls.UPDATE
+ if 'created' in kwargs and kwargs['created']:
+ cls.objs_created += 1
+ is_created = True
+ action = cls.ADD
+ else:
+ cls.objs_updated += 1
+
+ cls.log_data.append({
+ 'action': action,
+ 'sender': kwargs['sender'],
+ 'pk': kwargs['instance'].pk,
+ 'is_created': is_created,
+ })
+ track_save = classmethod(_track_save)
+
+ def _track_delete(cls, *args, **kwargs):
+ cls.objs_deleted += 1
+ cls.log_data.append({
+ 'action': cls.DELETE,
+ 'pk': kwargs['instance'].pk,
+ 'sender': kwargs['sender'],
+ })
+ track_delete = classmethod(_track_delete)
+
+ def _connect(cls):
+ post_save.connect(cls.track_save)
+ post_delete.connect(cls.track_delete)
+ cls.update_objects_state()
+ connect = classmethod(_connect)
+
+ def _update_objects_state(cls):
+ for md in models.get_models():
+ model_name = cls.prepare_model_name(md)
+ try:
+ cls.objects_state[model_name] = md.objects.count()
+ except Exception:
+ pass
+ update_objects_state = classmethod(_update_objects_state)
+
+ def renew_state(self):
+ cls = self.__class__
+
+ cls.prev_objects_state = cls.objects_state.copy()
+ self.update_objects_state()
+
+ cls.objs_created = 0
+ cls.objs_updated = 0
+ cls.objs_deleted = 0
+ cls.log_data = []
+
+ def _prepare_model_name(cls, mdl):
+ return re.sub(r'(\\']*)', '', str(mdl)).strip()
+ prepare_model_name = classmethod(_prepare_model_name)
+
+ def _statistic(self):
+ cls = self.__class__
+ data = self.log_data
+ stat = {}
+ for item in data:
+ sender = cls.prepare_model_name(item['sender'])
+ action = item['action']
+ if not sender in stat:
+ stat[sender] = dict((key, 0) for key in self.keys.values())
+
+ stat[sender][self.keys[action]] += 1
+
+ return stat
+ statistic = property(_statistic)
+
+ def merge_states(self, stat, cur, prev):
+ rv = []
+ keys = self.keys.values()
+ for md, cur in cur.iteritems():
+ prev_amt = prev.get(md, -1)
+ md_stat = stat.get(md, None)
+
+ md_data = {
+ 'prev': prev_amt,
+ 'cur': cur,
+ 'model': md,
+ }
+
+ if md_stat:
+ [md_data.update({
+ 'have_%s' % key: True,
+ '%s_amount' % key: md_stat[key],
+ }) for key in keys if md_stat[key] > 0]
+
+ rv.append(md_data)
+
+ # sort by C/U/D
+ [rv.sort(reverse=True, key=lambda obj: obj.get(key, 0)) \
+ for key in ["%s_amount" % c_key for c_key in keys]]
+
+ return rv
+
+ def content(self):
+ context = self.context.copy()
+ statistic = self.statistic.copy()
+ context.update({
+ 'objs_created': self.objs_created,
+ 'objs_updated': self.objs_updated,
+ 'objs_deleted': self.objs_deleted,
+ 'stat': statistic,
+ 'objects_state': self.merge_states(statistic, self.objects_state, \
+ self.prev_objects_state),
+ })
+
+ # we should do it because we save state to
+ # class, not to particular object instance
+ self.renew_state()
+
+ return render_to_string('debug_toolbar/panels/state.html', context)
+
+# initialize tracking signals
+StateDebugPanel.connect()
diff --git a/debug_toolbar/templates/debug_toolbar/panels/state.html b/debug_toolbar/templates/debug_toolbar/panels/state.html
new file mode 100644
index 000000000..3af17a642
--- /dev/null
+++ b/debug_toolbar/templates/debug_toolbar/panels/state.html
@@ -0,0 +1,72 @@
+{% load i18n %}
+
+ {% trans "Summary" %}:
+
+ {% trans "Created" %}:
+ {{ objs_created }}
+ {% trans "Updated" %}:
+ {{ objs_updated }}
+ {% trans "Deleted" %}:
+ {{ objs_deleted }}
+
+
+
+
+{% ifequal stat|length 0 %}
+{% trans "No objects was created, updated or deleted" %}
+{% else %}
+{% trans "Objects manipulations statistic" %}
+
+
+
+ {% trans "Model" %}
+ {% trans 'Created' %}
+ {% trans 'Changed' %}
+ {% trans 'Deleted' %}
+
+
+
+ {% for sender, s in stat.iteritems %}
+
+ {{ sender }}
+ {{ s.created }}
+ {{ s.updated }}
+ {{ s.deleted }}
+
+ {% endfor %}
+
+
+{% endifequal %}
+
+{% trans "Objects state" %}
+
+{% trans "C" %} — {% trans "Created" %}
+
+{% trans "U" %} — {% trans "Updated" %}
+
+{% trans "D" %} — {% trans "Deleted" %}
+
+
+
+
+ {% trans "C" %}
+ {% trans "U" %}
+ {% trans "D" %}
+ {% trans "Model" %}
+ {% trans 'Objects amount' %}
+ {% trans 'Previous objects amount' %}
+
+
+
+ {% for item in objects_state %}
+
+ {{ item.created_amount }}
+ {{ item.updated_amount }}
+ {{ item.deleted_amount }}
+ {{ item.model }}
+ {{ item.cur }}
+ {{ item.prev }}
+
+ {% endfor %}
+
+
diff --git a/debug_toolbar/toolbar/loader.py b/debug_toolbar/toolbar/loader.py
index 4b53d2f79..2dfdcc561 100644
--- a/debug_toolbar/toolbar/loader.py
+++ b/debug_toolbar/toolbar/loader.py
@@ -32,6 +32,7 @@ def __init__(self, request):
#'debug_toolbar.panels.cache.CacheDebugPanel',
'debug_toolbar.panels.signals.SignalDebugPanel',
'debug_toolbar.panels.logger.LoggingPanel',
+ 'debug_toolbar.panels.state.StateDebugPanel',
)
self.load_panels()
diff --git a/debug_toolbar/views.py b/debug_toolbar/views.py
index bc6cdb33f..4f49fe373 100644
--- a/debug_toolbar/views.py
+++ b/debug_toolbar/views.py
@@ -24,6 +24,8 @@ def debug_media(request, path):
if root is None:
parent = os.path.abspath(os.path.dirname(__file__))
root = os.path.join(parent, 'media', 'debug_toolbar')
+ from django.http import HttpResponse
+ return HttpResponse(open(os.path.join(root,path)).read(), mimetype='text/css')
return django.views.static.serve(request, path, root)
def sql_select(request):
diff --git a/example/example.db b/example/example.db
index f78b9875f57648fe2c098e7da1f1c6053def7a54..9467dc57d175aff29c0b86e2bfc557c4c83a0339 100644
GIT binary patch
delta 3344
zcmai0du&tJ89(QIzP@%I&I6KbJK)@e&^RRtwqrva%7_7jfW(131_3pmV>`rdoCMn;
zG=-&?bloQPv2eO}MYt(J5TA$4z+RZ~YbAZ=;?XvIXOKK2mGAHcMod+lT5
zkgZm7^t<2lJihZg-=nX=qrV}IJqJ2s>8Lz3mP~}watqQSj8VHRBZNH&Av^o$KWVnn
zwT4NXKDG%=Ccq6
zd>gCzUc}y2I$V#9k?2S?9Sx>JiSdzWRYn#b4vik=GHa<0*I;8P63H4_=H$x1VXR|O
zZowH@;HW)^{=dwwGYM!Op?UmAqJug(Hmm$_uKmz{TyT0Vh?3WfXZp@0owQJIp|4DQ
zmHzvXNUN`O(?^cm1f5<2=^|VO;P`SEu0yZIR!aGQU
z{0@FieTF;w7QJ5DU6XS>t1l}QPuGj0xGf-TBF&ep`WF>S@Xaf9;Au8!wy1Vs$R)o^7%V0-Qr|
zj&0ww5FfxrNRle*i!sJNUnr7@jcP+Wno6tx?ds4R9!nsMTn?wR$>DBtxn-xP&C%M{
z;%IidTfL5!|D|!d)k49rh+vWB`wYxRkg%2jtFr^#if}6k(8{#;W0=`nNMAi-!=|~n
zkGzb9BE96V&Rf@qLV>PC@fXuqAFQL!q49pTHoTLX5TBp_DNX8a@aI=KVC
zS2qKp8Ka3lhZ}J@y_Bw)dk^o%aN1Nt4<
z=_jejnb%mltx8g-ZUhs8kKoVnD>w%;&<_uQ9ZYN)H;L736p*FLlBwzF39Ym(+a{ur&8hz
zIo;kCSHu+>3b%MdEsjXYKj!m|I#2j|+*=DW$LeWvw8~C*o2RAC
z;c0ekHn|;cZ{}RDA-Klo^bTySgHHTq^U;nR!*vALnbZ3~uTRURden*7-yJ+l%w!(=
zW)&|ejjQM@=~`@N8~^RyO8IJ0YG}YpFdZ5kiDow^O9uI0)*an`U$0;8^=%Ggfv#RT(AUvX(4golL}}{=tTe?&Bg|tWJscd5CKIt#DmFG6jJn;M
z9pO#UW%9LDzG^dYCGEU=e~DtL6s3J$tZdN&(XUTb8iRw8kjEKr39Dblw(Ruw1a|rl
z(eo4L;+(!#?g}tTm9_S0a%^He7>m?4C^jh*(7z<0GwN`vPF!0LMgay<`NUAts4
zT2#APlzMzv*^`Mndf93W4h;^49o``)WnU%o(x`H+Cd*l<-5$!1`gO9;L{sa5S=g>^9k#}H`TqJLhd2$`B
zQ!MpGiI0*yL29@L%d6)d0JVQoU7f_9F;y>XZ-~@gEThYJJ
zTj;0g2^428%YHVCfEsYkj?k#g9)CGis`2QOMqn;p^ehyq2?@+2cpv5&t-Ju!byWh|
zi0f6yOm`t?$Tz>&sI%s*GW`a(%IiL~Mh93~--4U)1$@E^_yf4giu*1211sxa!p~TV
z|Cl`iXW<#f@a<^Mq30)G(
z*w)}4q9fmgLiP$=M0;ly_w>nXQQE>tu|~VakvQv^#)7G6hP1*iPnbOgt@&bm{=Lpu
z2Dwk>g6AvMn;tze9!o}pkx)9ysL5!siPE+vtT^ehg-Q!2!mOM2!Uspjj@DD#LUj?>
zYMgWlSI{pO%1e}HONNK~mhcc~FO73*^5>i3A#QP(ho;rpEhjl-%}g(|JsNpyRHddY1?lT$M?^PFvSKA^3~1Tv7KWskxuFi8YfI14~|t
z@in5fc|BIj?xswzQV6jonlrnWE-PHWLaOEV^y1a(0tKzjZliX}Jl674zE3-4uFakD
ng9`<<&PS}fVz*}js%_xID|aGlBZB`6^AoBh
delta 2351
zcmbtVdu&rx7{90Y-t(1iV^3DxfE65LPrR=_?f|#R3R|HaY_QSBSZ;4$E4^K%9b@?y9F;{b)f;S
zLu5PAiYJri|_Ozk}Gd(?bBRb;*vZkXR8OhF$
zr|BsdOV+GghVYDU-3f#+fewy=OfgN;t1P6W;WqNpssV$@kg_HLu`?&@UFa@-!_qRn
zD>jzs{bD9Y!RPP-+z~CFtj4ZoYnUs{d(6wsAtp9c
zUi>qiJ-mJ<7JY(tm~trCLctI437mx&;TRl*JrIO`=!6!i1{(i_Kf~wnbNDg*0FL4T
z9a+GZS(H}~|AJ;Lrf(54&dz5n#b4>rEl0}OLW#t(pi!XZ?U*z@ktsvPRBcI#m_i73
zb%pjSS~4EW51sjOwK}4uq6%Mc7bS<@C*>x4)F4^08ZZ$89oW$kAf#50ySLZrZ
zTTw*UqWp<;{oTK
z#r$^94q*cy+!&39gF8HNH7+N8Jx=Gq*am)cEV|1#2+Kv7#-#J=bX;p%p
zEnu@*?RJ}J3s@ybNEB7o#yRW`PLU<1UPsC$@t<-?=WdzN;Gqm2+D|{jXiVt~tQQ}{
z-{J;*AC$rVZ02@4(_KV0?
zvtK6fuUtwtu4*c(m|R>2=C(F8rIHVtSE5RCr8zQd|6NZdIoeQ@Un`n&-Xpk3!NoZ|
zw55n#^ji#t+%unS=d;m&vngYw#gL@nSGWq7;SziU=iyWM7~X@ob;f!FUV{_xjLvOO
z!cm>O9)d~z9ohrQJWKS_B$;}=@FAFglKGMYY&pYF48u6tN7!%h82%n2I_PEE&{0m#
zwcJ@$HR-GXb5|ESu!y*uWVDD(H{JVZAWt>)lda85_3(}~_jgohDyqP|sRd=$3@3s*
ziI1kE{$yykHk?Wgk0ku+NFp6dr2XmfWXL}pEKr-tJIb=s0vmE!X}%+|2+Y=%C{y|u
zsuoJ6lt{=wnhNc{0hO06CTpf^A+I3!OxM{TtOoPCHk7HGT_21oiO7gw32MU$e|#iz
w1EWxW8$k!_{=~U3eS2r7+6-p54%BgLpn|g(0@maJ=Q(&`x~9Bf;fkg|0P$R?O8@`>
diff --git a/example/models.py b/example/models.py
new file mode 100644
index 000000000..6cdc79dc1
--- /dev/null
+++ b/example/models.py
@@ -0,0 +1,8 @@
+from django.db import models
+
+
+class Sample(models.Model):
+ name = models.CharField(max_length=255)
+
+ def __unicode__(self):
+ return self.name
diff --git a/example/settings.py b/example/settings.py
index 06e153d99..f08d66818 100644
--- a/example/settings.py
+++ b/example/settings.py
@@ -1,6 +1,10 @@
import os
+import sys
+
PROJECT_PATH = os.path.realpath(os.path.dirname(__file__))
+sys.path.append(os.path.join(PROJECT_PATH, '..'))
+
ADMIN_MEDIA_PREFIX = '/admin_media/'
DATABASE_ENGINE = 'sqlite3'
DATABASE_NAME = 'example.db'
@@ -12,6 +16,7 @@
'django.contrib.sessions',
'django.contrib.sites',
'debug_toolbar',
+ 'example',
)
INTERNAL_IPS = ('127.0.0.1',)
MEDIA_ROOT = os.path.join(PROJECT_PATH, 'media')
diff --git a/example/urls.py b/example/urls.py
index 25acc3168..e73670afa 100644
--- a/example/urls.py
+++ b/example/urls.py
@@ -6,7 +6,7 @@
admin.autodiscover()
urlpatterns = patterns('',
- (r'^$', direct_to_template, {'template': 'index.html'}),
+ (r'^$', 'example.views.update_object', {'template': 'index.html'}),
(r'^jquery/index/$', direct_to_template, {'template': 'jquery/index.html'}),
(r'^mootools/index/$', direct_to_template, {'template': 'mootools/index.html'}),
(r'^prototype/index/$', direct_to_template, {'template': 'prototype/index.html'}),
diff --git a/example/views.py b/example/views.py
new file mode 100644
index 000000000..e4b76f62a
--- /dev/null
+++ b/example/views.py
@@ -0,0 +1,33 @@
+from django.views.generic.simple import direct_to_template
+from django.contrib.auth.models import User
+
+from models import Sample
+
+
+def update_object(request, template=''):
+ # create object
+ obj = Sample.objects.create(name='test')
+ obj = Sample.objects.all().order_by('?')[0]
+
+ # update objec
+ obj.name = 'test1'
+ obj.save()
+
+ # update objec
+ obj.name = 'test2'
+ obj.save()
+
+ # delete object
+ obj.delete()
+
+ obj2 = Sample.objects.create(name='test2')
+
+ user, created = User.objects.get_or_create(username='admin', defaults={
+ 'username': 'admin',
+ 'email': 'test@test.com',
+ 'first_name': 'admin',
+ 'last_name': 'admin',
+ })
+ user.last_name = 'test'
+ user.save()
+ return direct_to_template(request, template=template)
From f9a950f208a9705803838753a394a3509fa4ead7 Mon Sep 17 00:00:00 2001
From: Max Klymyshyn
Date: Mon, 25 Apr 2011 22:21:13 +0300
Subject: [PATCH 02/10] Removed debug code from views.py
---
debug_toolbar/views.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/debug_toolbar/views.py b/debug_toolbar/views.py
index 4f49fe373..bc6cdb33f 100644
--- a/debug_toolbar/views.py
+++ b/debug_toolbar/views.py
@@ -24,8 +24,6 @@ def debug_media(request, path):
if root is None:
parent = os.path.abspath(os.path.dirname(__file__))
root = os.path.join(parent, 'media', 'debug_toolbar')
- from django.http import HttpResponse
- return HttpResponse(open(os.path.join(root,path)).read(), mimetype='text/css')
return django.views.static.serve(request, path, root)
def sql_select(request):
From e1188657808a796dd74916dd5b1cc93b826beefa Mon Sep 17 00:00:00 2001
From: Max Klymyshyn
Date: Wed, 11 May 2011 11:00:42 +0300
Subject: [PATCH 03/10] Added HTML Validator panel and additional configuration
settings DEBUG_ROOLBAR_DEV to develop debug_toolbar enhancement without
tweaking of its templates
---
.../media/debug_toolbar/css/toolbar.css | 87 +++++++++++++++++-
.../media/debug_toolbar/css/toolbar.min.css | 2 +-
.../media/debug_toolbar/js/toolbar.js | 30 +++++-
.../media/debug_toolbar/js/toolbar.min.js | 2 +-
debug_toolbar/panels/htmlvalidator.py | 92 +++++++++++++++++++
.../templates/debug_toolbar/base.html | 5 +
.../debug_toolbar/panels/htmlvalidator.html | 29 ++++++
debug_toolbar/toolbar/loader.py | 5 +-
example/settings.py | 5 +
example/templates/index.html | 6 +-
10 files changed, 257 insertions(+), 6 deletions(-)
create mode 100644 debug_toolbar/panels/htmlvalidator.py
create mode 100644 debug_toolbar/templates/debug_toolbar/panels/htmlvalidator.html
diff --git a/debug_toolbar/media/debug_toolbar/css/toolbar.css b/debug_toolbar/media/debug_toolbar/css/toolbar.css
index e21b38dd0..fdd3064a3 100644
--- a/debug_toolbar/media/debug_toolbar/css/toolbar.css
+++ b/debug_toolbar/media/debug_toolbar/css/toolbar.css
@@ -467,4 +467,89 @@
#djDebug table td.io-cell {
border-top:1px solid #fff;
text-align:center;
-}
\ No newline at end of file
+}
+
+/**
+ * HTML Validator panel style
+*/
+#djDebug .panelContent .djDebug-htmlvalidator-summary {
+ /* pass */
+}
+
+#djDebug .panelContent .djDebug-htmlvalidator-summary legend {
+ font-size:1.4em;
+ padding-bottom:0.5em;
+}
+
+#djDebug .panelContent .djDebug-htmlvalidator-summary pre {
+ display:block;
+ font-family:"Courier New", courier, fixed;
+ font-weight:bold;
+ cursor:pointer;
+}
+
+#djDebug .panelContent .djDebug-htmlvalidator-summary td.tidy-msg {
+ width:90%;
+}
+#djDebug .panelContent .djDebug-htmlvalidator-summary td.validation-error {
+ background-color:#F79A83;
+}
+
+#djDebug .panelContent .djDebug-htmlvalidator-summary .line-number {
+ display:block;
+ float:left;
+ width:35px;
+ padding-left:5px;
+ font-size:1em;
+ height:1em;
+}
+
+#djDebug .panelContent .djDebug-htmlvalidator-summary table td {
+ border-bottom:1px solid #9a9a9a;
+}
+
+#djDebug .panelContent .djDebug-htmlvalidator-summary table td {
+ border-bottom:1px solid #9a9a9a;
+}
+
+
+#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-content-code {
+ border:0;
+ background:transparent;
+ font-family:"Monaco", "Courier New", courier, fixed;
+ font-size:1em;
+ padding:0;
+ padding-left:40px;
+ border-bottom:1px dashed #8a8a8a;
+ margin-left:-40px;
+ height:1.3em;
+ line-height:1.3em;
+ font-weight:normal;
+}
+
+#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-line-sel {
+ background-color:#82E3F7;
+ -webkit-transition: background-color linear;
+ -webkit-transition-duration: 0.2s;
+ -ms-transition: background-color linear;
+ -ms-transition-duration: 0.2s;
+}
+
+#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-content {
+ background-color:#fff;
+ border:3px solid #676767;
+ width:100%;
+}
+
+#djDebug .panelContent .djDebug-htmlvalidator-summary .clean {
+ clear:both;
+}
+
+#djdebug .panelContent .djDebug-htmlvalidator-summary th {
+ text-align:left;
+ border-bottom:2px solid #898989;
+}
+#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-info-sel td.validation-error,
+#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-info-sel {
+ background-color:#83F7A8;
+}
diff --git a/debug_toolbar/media/debug_toolbar/css/toolbar.min.css b/debug_toolbar/media/debug_toolbar/css/toolbar.min.css
index e5aee0adc..89e9d7851 100644
--- a/debug_toolbar/media/debug_toolbar/css/toolbar.min.css
+++ b/debug_toolbar/media/debug_toolbar/css/toolbar.min.css
@@ -1 +1 @@
-#djDebug{color:#000;background:#FFF}#djDebug,#djDebug div,#djDebug span,#djDebug applet,#djDebug object,#djDebug iframe,#djDebug h1,#djDebug h2,#djDebug h3,#djDebug h4,#djDebug h5,#djDebug h6,#djDebug p,#djDebug blockquote,#djDebug pre,#djDebug a,#djDebug abbr,#djDebug acronym,#djDebug address,#djDebug big,#djDebug cite,#djDebug code,#djDebug del,#djDebug dfn,#djDebug em,#djDebug font,#djDebug img,#djDebug ins,#djDebug kbd,#djDebug q,#djDebug s,#djDebug samp,#djDebug small,#djDebug strike,#djDebug strong,#djDebug sub,#djDebug sup,#djDebug tt,#djDebug var,#djDebug b,#djDebug u,#djDebug i,#djDebug center,#djDebug dl,#djDebug dt,#djDebug dd,#djDebug ol,#djDebug ul,#djDebug li,#djDebug fieldset,#djDebug form,#djDebug label,#djDebug legend,#djDebug table,#djDebug caption,#djDebug tbody,#djDebug tfoot,#djDebug thead,#djDebug tr,#djDebug th,#djDebug td{margin:0;padding:0;border:0;outline:0;font-size:12px;line-height:1.5em;color:#000;vertical-align:baseline;background:transparent;font-family:sans-serif;text-align:left}#djDebug #djDebugToolbar{background:#111;width:200px;z-index:100000000;position:fixed;top:0;bottom:0;right:0;opacity:.9}#djDebug #djDebugToolbar small{color:#999}#djDebug #djDebugToolbar ul{margin:0;padding:0;list-style:none}#djDebug #djDebugToolbar li{border-bottom:1px solid #222;color:#fff;display:block;font-weight:bold;float:none;margin:0;padding:0;position:relative;width:auto}#djDebug #djDebugToolbar li>a,#djDebug #djDebugToolbar li>div.contentless{font-weight:normal;font-style:normal;text-decoration:none;display:block;font-size:16px;padding:10px 10px 5px 25px;color:#fff}#djDebug #djDebugToolbar li a:hover{color:#111;background-color:#ffc}#djDebug #djDebugToolbar li.active{background-image:url(../img/indicator.png);background-repeat:no-repeat;background-position:left center;background-color:#333;padding-left:10px}#djDebug #djDebugToolbar li.active a:hover{color:#b36a60;background-color:transparent}#djDebug #djDebugToolbar li small{font-size:12px;color:#999;font-style:normal;text-decoration:none;font-variant:small-caps}#djDebug #djDebugToolbarHandle{position:fixed;background:#fff;border:1px solid #111;top:30px;right:0;z-index:100000000;opacity:.75}#djDebug a#djShowToolBarButton{display:block;height:75px;width:30px;border-right:none;border-bottom:4px solid #fff;border-top:4px solid #fff;border-left:4px solid #fff;color:#fff;font-size:10px;font-weight:bold;text-decoration:none;text-align:center;text-indent:-999999px;background:#000 url(../img/djdt_vertical.png) no-repeat left center;opacity:.5}#djDebug a#djShowToolBarButton:hover{background-color:#111;padding-right:6px;border-top-color:#ffe761;border-left-color:#ffe761;border-bottom-color:#ffe761;opacity:1.0}#djDebug code{display:block;font-family:Consolas,Monaco,"Bitstream Vera Sans Mono","Lucida Console",monospace;white-space:pre;overflow:auto}#djDebug tr.djDebugOdd{background-color:#f5f5f5}#djDebug .panelContent{display:none;position:fixed;margin:0;top:0;right:200px;bottom:0;left:0;background-color:#eee;color:#666;z-index:100000000}#djDebug .panelContent>div{border-bottom:1px solid #ddd}#djDebug .djDebugPanelTitle{position:absolute;background-color:#ffc;color:#666;padding-left:20px;top:0;right:0;left:0;height:50px}#djDebug .djDebugPanelTitle code{display:inline;font-size:inherit}#djDebug .djDebugPanelContent{position:absolute;top:50px;right:0;bottom:0;left:0;height:auto;padding:0 0 0 20px}#djDebug .djDebugPanelContent .scroll{height:100%;overflow:auto;display:block;padding:0 10px 0 0}#djDebug h3{font-size:24px;font-weight:normal;line-height:50px}#djDebug h4{font-size:20px;font-weight:bold;margin-top:.8em}#djDebug .panelContent table{border:1px solid #ccc;border-collapse:collapse;width:100%;background-color:#fff;display:block;margin-top:.8em;overflow:auto}#djDebug .panelContent tbody td,#djDebug .panelContent tbody th{vertical-align:top;padding:2px 3px}#djDebug .panelContent thead th{padding:1px 6px 1px 3px;text-align:left;font-weight:bold;font-size:14px}#djDebug .panelContent tbody th{width:12em;text-align:right;color:#666;padding-right:.5em}#djDebug .djTemplateHideContextDiv{background-color:#fff}#djDebug .panelContent .djDebugClose{text-indent:-9999999px;display:block;position:absolute;top:4px;right:15px;height:40px;width:40px;background:url(../img/close.png) no-repeat center center}#djDebug .panelContent .djDebugClose:hover{background-image:url(../img/close_hover.png)}#djDebug .panelContent .djDebugClose.djDebugBack{background-image:url(../img/back.png)}#djDebug .panelContent .djDebugClose.djDebugBack:hover{background-image:url(../img/back_hover.png)}#djDebug .panelContent dt,#djDebug .panelContent dd{display:block}#djDebug .panelContent dt{margin-top:.75em}#djDebug .panelContent dd{margin-left:10px}#djDebug a.toggleTemplate{padding:4px;background-color:#bbb;-moz-border-radius:3px;-webkit-border-radius:3px}#djDebug a.toggleTemplate:hover{padding:4px;background-color:#444;color:#ffe761;-moz-border-radius:3px;-webkit-border-radius:3px}#djDebug a.djTemplateShowContext,#djDebug a.djTemplateShowContext span.toggleArrow{color:#999}#djDebug a.djTemplateShowContext:hover,#djDebug a.djTemplateShowContext:hover span.toggleArrow{color:#000;cursor:pointer}#djDebug .djDebugSqlWrap{position:relative}#djDebug .djDebugSql{z-index:100000002}#djDebug .djSQLHideStacktraceDiv tbody th{text-align:left}#djDebug .djSqlExplain td{white-space:pre}#djDebug span.djDebugLineChart{background-color:#777;height:3px;position:absolute;bottom:0;top:0;left:0;display:block;z-index:1000000001}#djDebug span.djDebugLineChartWarning{background-color:#900}#djDebug .highlight{color:#000}#djDebug .highlight .err{color:#000}#djDebug .highlight .g{color:#000}#djDebug .highlight .k{color:#000;font-weight:bold}#djDebug .highlight .o{color:#000}#djDebug .highlight .n{color:#000}#djDebug .highlight .mi{color:#000;font-weight:bold}#djDebug .highlight .l{color:#000}#djDebug .highlight .x{color:#000}#djDebug .highlight .p{color:#000}#djDebug .highlight .m{color:#000;font-weight:bold}#djDebug .highlight .s{color:#333}#djDebug .highlight .w{color:#888}#djDebug .highlight .il{color:#000;font-weight:bold}#djDebug .highlight .na{color:#333}#djDebug .highlight .nt{color:#000;font-weight:bold}#djDebug .highlight .nv{color:#333}#djDebug .highlight .s2{color:#333}#djDebug .highlight .cp{color:#333}@media print{#djDebug{display:none}}#djDebug .created,#djDebug tr.created-obj{background-color:#83f7a8}#djDebug .updated,#djDebug tr.updated-obj{background-color:#82e3f7}#djDebug .deleted,#djDebug tr.deleted-obj{background-color:#f79a83}#djDebug span.deleted,#djDebug span.updated,#djDebug span.created{display:inline;display:inline-block;padding:3px}#djDebug .djDebug-state-summary{overflow:hidden;width:100%}#djDebug .djDebug-state-summary legend{font-size:1.3em;padding-top:1em}#djDebug .djDebug-state-summary dl{clear:both;margin-top:15px}#djDebug dt.deleted{float:left}#djDebug .panelContent .djDebug-state-summary dt,#djDebug .panelContent .djDebug-state-summary dd{margin:0;padding:0;float:left}#djDebug .panelContent .djDebug-state-summary dt{font-size:1.2em;padding-left:.3em;padding-right:.3em}#djDebug .panelContent .djDebug-state-summary dd{font-size:1.4em;font-weight:bold;padding-left:10px;padding-right:20px;line-height:1.2em}#djDebug table th.io-cell,#djDebug table td.io-cell{border-top:1px solid #fff;text-align:center}
\ No newline at end of file
+#djDebug{color:#000;background:#FFF}#djDebug,#djDebug div,#djDebug span,#djDebug applet,#djDebug object,#djDebug iframe,#djDebug h1,#djDebug h2,#djDebug h3,#djDebug h4,#djDebug h5,#djDebug h6,#djDebug p,#djDebug blockquote,#djDebug pre,#djDebug a,#djDebug abbr,#djDebug acronym,#djDebug address,#djDebug big,#djDebug cite,#djDebug code,#djDebug del,#djDebug dfn,#djDebug em,#djDebug font,#djDebug img,#djDebug ins,#djDebug kbd,#djDebug q,#djDebug s,#djDebug samp,#djDebug small,#djDebug strike,#djDebug strong,#djDebug sub,#djDebug sup,#djDebug tt,#djDebug var,#djDebug b,#djDebug u,#djDebug i,#djDebug center,#djDebug dl,#djDebug dt,#djDebug dd,#djDebug ol,#djDebug ul,#djDebug li,#djDebug fieldset,#djDebug form,#djDebug label,#djDebug legend,#djDebug table,#djDebug caption,#djDebug tbody,#djDebug tfoot,#djDebug thead,#djDebug tr,#djDebug th,#djDebug td{margin:0;padding:0;border:0;outline:0;font-size:12px;line-height:1.5em;color:#000;vertical-align:baseline;background:transparent;font-family:sans-serif;text-align:left}#djDebug #djDebugToolbar{background:#111;width:200px;z-index:100000000;position:fixed;top:0;bottom:0;right:0;opacity:.9}#djDebug #djDebugToolbar small{color:#999}#djDebug #djDebugToolbar ul{margin:0;padding:0;list-style:none}#djDebug #djDebugToolbar li{border-bottom:1px solid #222;color:#fff;display:block;font-weight:bold;float:none;margin:0;padding:0;position:relative;width:auto}#djDebug #djDebugToolbar li>a,#djDebug #djDebugToolbar li>div.contentless{font-weight:normal;font-style:normal;text-decoration:none;display:block;font-size:16px;padding:10px 10px 5px 25px;color:#fff}#djDebug #djDebugToolbar li a:hover{color:#111;background-color:#ffc}#djDebug #djDebugToolbar li.active{background-image:url(../img/indicator.png);background-repeat:no-repeat;background-position:left center;background-color:#333;padding-left:10px}#djDebug #djDebugToolbar li.active a:hover{color:#b36a60;background-color:transparent}#djDebug #djDebugToolbar li small{font-size:12px;color:#999;font-style:normal;text-decoration:none;font-variant:small-caps}#djDebug #djDebugToolbarHandle{position:fixed;background:#fff;border:1px solid #111;top:30px;right:0;z-index:100000000;opacity:.75}#djDebug a#djShowToolBarButton{display:block;height:75px;width:30px;border-right:none;border-bottom:4px solid #fff;border-top:4px solid #fff;border-left:4px solid #fff;color:#fff;font-size:10px;font-weight:bold;text-decoration:none;text-align:center;text-indent:-999999px;background:#000 url(../img/djdt_vertical.png) no-repeat left center;opacity:.5}#djDebug a#djShowToolBarButton:hover{background-color:#111;padding-right:6px;border-top-color:#ffe761;border-left-color:#ffe761;border-bottom-color:#ffe761;opacity:1.0}#djDebug code{display:block;font-family:Consolas,Monaco,"Bitstream Vera Sans Mono","Lucida Console",monospace;white-space:pre;overflow:auto}#djDebug tr.djDebugOdd{background-color:#f5f5f5}#djDebug .panelContent{display:none;position:fixed;margin:0;top:0;right:200px;bottom:0;left:0;background-color:#eee;color:#666;z-index:100000000}#djDebug .panelContent>div{border-bottom:1px solid #ddd}#djDebug .djDebugPanelTitle{position:absolute;background-color:#ffc;color:#666;padding-left:20px;top:0;right:0;left:0;height:50px}#djDebug .djDebugPanelTitle code{display:inline;font-size:inherit}#djDebug .djDebugPanelContent{position:absolute;top:50px;right:0;bottom:0;left:0;height:auto;padding:0 0 0 20px}#djDebug .djDebugPanelContent .scroll{height:100%;overflow:auto;display:block;padding:0 10px 0 0}#djDebug h3{font-size:24px;font-weight:normal;line-height:50px}#djDebug h4{font-size:20px;font-weight:bold;margin-top:.8em}#djDebug .panelContent table{border:1px solid #ccc;border-collapse:collapse;width:100%;background-color:#fff;display:block;margin-top:.8em;overflow:auto}#djDebug .panelContent tbody td,#djDebug .panelContent tbody th{vertical-align:top;padding:2px 3px}#djDebug .panelContent thead th{padding:1px 6px 1px 3px;text-align:left;font-weight:bold;font-size:14px}#djDebug .panelContent tbody th{width:12em;text-align:right;color:#666;padding-right:.5em}#djDebug .djTemplateHideContextDiv{background-color:#fff}#djDebug .panelContent .djDebugClose{text-indent:-9999999px;display:block;position:absolute;top:4px;right:15px;height:40px;width:40px;background:url(../img/close.png) no-repeat center center}#djDebug .panelContent .djDebugClose:hover{background-image:url(../img/close_hover.png)}#djDebug .panelContent .djDebugClose.djDebugBack{background-image:url(../img/back.png)}#djDebug .panelContent .djDebugClose.djDebugBack:hover{background-image:url(../img/back_hover.png)}#djDebug .panelContent dt,#djDebug .panelContent dd{display:block}#djDebug .panelContent dt{margin-top:.75em}#djDebug .panelContent dd{margin-left:10px}#djDebug a.toggleTemplate{padding:4px;background-color:#bbb;-moz-border-radius:3px;-webkit-border-radius:3px}#djDebug a.toggleTemplate:hover{padding:4px;background-color:#444;color:#ffe761;-moz-border-radius:3px;-webkit-border-radius:3px}#djDebug a.djTemplateShowContext,#djDebug a.djTemplateShowContext span.toggleArrow{color:#999}#djDebug a.djTemplateShowContext:hover,#djDebug a.djTemplateShowContext:hover span.toggleArrow{color:#000;cursor:pointer}#djDebug .djDebugSqlWrap{position:relative}#djDebug .djDebugSql{z-index:100000002}#djDebug .djSQLHideStacktraceDiv tbody th{text-align:left}#djDebug .djSqlExplain td{white-space:pre}#djDebug span.djDebugLineChart{background-color:#777;height:3px;position:absolute;bottom:0;top:0;left:0;display:block;z-index:1000000001}#djDebug span.djDebugLineChartWarning{background-color:#900}#djDebug .highlight{color:#000}#djDebug .highlight .err{color:#000}#djDebug .highlight .g{color:#000}#djDebug .highlight .k{color:#000;font-weight:bold}#djDebug .highlight .o{color:#000}#djDebug .highlight .n{color:#000}#djDebug .highlight .mi{color:#000;font-weight:bold}#djDebug .highlight .l{color:#000}#djDebug .highlight .x{color:#000}#djDebug .highlight .p{color:#000}#djDebug .highlight .m{color:#000;font-weight:bold}#djDebug .highlight .s{color:#333}#djDebug .highlight .w{color:#888}#djDebug .highlight .il{color:#000;font-weight:bold}#djDebug .highlight .na{color:#333}#djDebug .highlight .nt{color:#000;font-weight:bold}#djDebug .highlight .nv{color:#333}#djDebug .highlight .s2{color:#333}#djDebug .highlight .cp{color:#333}@media print{#djDebug{display:none}}#djDebug .created,#djDebug tr.created-obj{background-color:#83f7a8}#djDebug .updated,#djDebug tr.updated-obj{background-color:#82e3f7}#djDebug .deleted,#djDebug tr.deleted-obj{background-color:#f79a83}#djDebug span.deleted,#djDebug span.updated,#djDebug span.created{display:inline;display:inline-block;padding:3px}#djDebug .djDebug-state-summary{overflow:hidden;width:100%}#djDebug .djDebug-state-summary legend{font-size:1.3em;padding-top:1em}#djDebug .djDebug-state-summary dl{clear:both;margin-top:15px}#djDebug dt.deleted{float:left}#djDebug .panelContent .djDebug-state-summary dt,#djDebug .panelContent .djDebug-state-summary dd{margin:0;padding:0;float:left}#djDebug .panelContent .djDebug-state-summary dt{font-size:1.2em;padding-left:.3em;padding-right:.3em}#djDebug .panelContent .djDebug-state-summary dd{font-size:1.4em;font-weight:bold;padding-left:10px;padding-right:20px;line-height:1.2em}#djDebug table th.io-cell,#djDebug table td.io-cell{border-top:1px solid #fff;text-align:center}#djDebug .panelContent .djDebug-htmlvalidator-summary legend{font-size:1.4em;padding-bottom:.5em}#djDebug .panelContent .djDebug-htmlvalidator-summary pre{display:block;font-family:"Courier New",courier,fixed;font-weight:bold;cursor:pointer}#djDebug .panelContent .djDebug-htmlvalidator-summary td.tidy-msg{width:90%}#djDebug .panelContent .djDebug-htmlvalidator-summary td.validation-error{background-color:#f79a83}#djDebug .panelContent .djDebug-htmlvalidator-summary .line-number{display:block;float:left;width:35px;padding-left:5px;font-size:1em;height:1em}#djDebug .panelContent .djDebug-htmlvalidator-summary table td{border-bottom:1px solid #9a9a9a}#djDebug .panelContent .djDebug-htmlvalidator-summary table td{border-bottom:1px solid #9a9a9a}#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-content-code{border:0;background:transparent;font-family:"Monaco","Courier New",courier,fixed;font-size:1em;padding:0;padding-left:40px;border-bottom:1px dashed #8a8a8a;margin-left:-40px;height:1.3em;line-height:1.3em;font-weight:normal}#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-line-sel{background-color:#82e3f7;-webkit-transition:background-color linear;-webkit-transition-duration:.2s;-ms-transition:background-color linear;-ms-transition-duration:.2s}#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-content{background-color:#fff;border:3px solid #676767;width:100%}#djDebug .panelContent .djDebug-htmlvalidator-summary .clean{clear:both}#djdebug .panelContent .djDebug-htmlvalidator-summary th{text-align:left;border-bottom:2px solid #898989}#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-info-sel td.validation-error,#djDebug .panelContent .djDebug-htmlvalidator-summary .repr-info-sel{background-color:#83f7a8}
\ No newline at end of file
diff --git a/debug_toolbar/media/debug_toolbar/js/toolbar.js b/debug_toolbar/media/debug_toolbar/js/toolbar.js
index a43d834a5..cc4887f66 100644
--- a/debug_toolbar/media/debug_toolbar/js/toolbar.js
+++ b/debug_toolbar/media/debug_toolbar/js/toolbar.js
@@ -16,7 +16,14 @@
})(window, document, "1.3", function($, jquery_loaded) {
$.cookie = function(name, value, options) { if (typeof value != 'undefined') { options = options || {}; if (value === null) { value = ''; options.expires = -1; } var expires = ''; if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) { var date; if (typeof options.expires == 'number') { date = new Date(); date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000)); } else { date = options.expires; } expires = '; expires=' + date.toUTCString(); } var path = options.path ? '; path=' + (options.path) : ''; var domain = options.domain ? '; domain=' + (options.domain) : ''; var secure = options.secure ? '; secure' : ''; document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join(''); } else { var cookieValue = null; if (document.cookie && document.cookie != '') { var cookies = document.cookie.split(';'); for (var i = 0; i < cookies.length; i++) { var cookie = $.trim(cookies[i]); if (cookie.substring(0, name.length + 1) == (name + '=')) { cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); break; } } } return cookieValue; } };
- $('head').append(' ');
+ var debug_toolbar_css = 'toolbar.min.css';
+ if(DEBUG_TOOLBAR_DEV){
+ var rand = Math.round(Math.random() * 1000);
+ // avoid css caching here
+ debug_toolbar_css = 'toolbar.css?' + rand;
+ }
+ $('head').append(' ');
var COOKIE_NAME = 'djdt';
var djdt = {
init: function() {
@@ -74,6 +81,27 @@
djdt.show_toolbar();
return false;
});
+
+ $('.handle-position').click(function(){
+ $('.repr-info-sel').removeClass('repr-info-sel');
+ $(this).parent().parent().addClass('repr-info-sel')
+ var text = $(this).text();
+ var re = new RegExp('line\\s+([0-9]+)');
+ var result = text.match(re);
+
+ try{
+ var lineno = result[1];
+ }catch(e){return;}
+ //
+ var prevPos = $(document).data('reprlineselpos') || null;
+ if(prevPos){
+ prevPos.removeClass('repr-line-sel');
+ }
+ $('.repr-line-' + lineno).addClass('repr-line-sel');
+ $(document).data('reprlineselpos', $('.repr-line-' + lineno));
+ // TODO: skip pervious link and add new one
+ location = location + '#' + 'repr-line-' + lineno;
+ });
$(document).bind('close.djDebug', function() {
// If a sub-panel is open, close that
if ($('#djDebugWindow').is(':visible')) {
diff --git a/debug_toolbar/media/debug_toolbar/js/toolbar.min.js b/debug_toolbar/media/debug_toolbar/js/toolbar.min.js
index 73c01b8d2..877eab1af 100644
--- a/debug_toolbar/media/debug_toolbar/js/toolbar.min.js
+++ b/debug_toolbar/media/debug_toolbar/js/toolbar.min.js
@@ -1 +1 @@
-(function(g,a,b,i){var f,h;var e=false;if(!(f=g.jQuery)||b>f.fn.jquery||i(f)){var c=a.createElement("script");c.type="text/javascript";c.src=DEBUG_TOOLBAR_MEDIA_URL+"js/jquery.js";c.onload=c.onreadystatechange=function(){if(!e&&(!(h=this.readyState)||h=="loaded"||h=="complete")){i((f=g.jQuery).noConflict(1),e=true);f(c).remove()}};a.documentElement.childNodes[0].appendChild(c)}})(window,document,"1.3",function(b,a){b.cookie=function(f,n,q){if(typeof n!="undefined"){q=q||{};if(n===null){n="";q.expires=-1}var j="";if(q.expires&&(typeof q.expires=="number"||q.expires.toUTCString)){var k;if(typeof q.expires=="number"){k=new Date();k.setTime(k.getTime()+(q.expires*24*60*60*1000))}else{k=q.expires}j="; expires="+k.toUTCString()}var p=q.path?"; path="+(q.path):"";var l=q.domain?"; domain="+(q.domain):"";var e=q.secure?"; secure":"";document.cookie=[f,"=",encodeURIComponent(n),j,p,l,e].join("")}else{var h=null;if(document.cookie&&document.cookie!=""){var o=document.cookie.split(";");for(var m=0;m ');var d="djdt";var c={init:function(){b("#djDebug").show();var e=null;b("#djDebugPanelList li a").click(function(){if(!this.className){return false}e=b("#djDebug #"+this.className);if(e.is(":visible")){b(document).trigger("close.djDebug");b(this).parent().removeClass("active")}else{b(".panelContent").hide();e.show();b("#djDebugToolbar li").removeClass("active");b(this).parent().addClass("active")}return false});b("#djDebug a.djDebugClose").click(function(){b(document).trigger("close.djDebug");b("#djDebugToolbar li").removeClass("active");return false});b("#djDebug a.remoteCall").click(function(){b("#djDebugWindow").load(this.href,function(g,f,i){if(f=="error"){var h='Back '+i.status+": "+i.statusText+" ";b("#djDebugWindow").html(h)}b("#djDebugWindow a.djDebugBack").click(function(){b(this).parent().parent().hide();return false})});b("#djDebugWindow").show();return false});b("#djDebugTemplatePanel a.djTemplateShowContext").click(function(){c.toggle_arrow(b(this).children(".toggleArrow"));c.toggle_content(b(this).parent().next());return false});b("#djDebugSQLPanel a.djSQLShowStacktrace").click(function(){c.toggle_content(b(".djSQLHideStacktraceDiv",b(this).parents("tr")));return false});b("#djHideToolBarButton").click(function(){c.hide_toolbar(true);return false});b("#djShowToolBarButton").click(function(){c.show_toolbar();return false});b(document).bind("close.djDebug",function(){if(b("#djDebugWindow").is(":visible")){b("#djDebugWindow").hide();return}if(b(".panelContent").is(":visible")){b(".panelContent").hide();return}if(b("#djDebugToolbar").is(":visible")){c.hide_toolbar(true);return}});if(b.cookie(d)){c.hide_toolbar(false)}else{c.show_toolbar(false)}},toggle_content:function(e){if(e.is(":visible")){e.hide()}else{e.show()}},close:function(){b(document).trigger("close.djDebug");return false},hide_toolbar:function(e){b("#djDebugWindow").hide();b(".panelContent").hide();b("#djDebugToolbar li").removeClass("active");b("#djDebugToolbar").hide("fast");b("#djDebugToolbarHandle").show();b(document).unbind("keydown.djDebug");if(e){b.cookie(d,"hide",{path:"/",expires:10})}},show_toolbar:function(e){b(document).bind("keydown.djDebug",function(f){if(f.keyCode==27){c.close()}});b("#djDebugToolbarHandle").hide();if(e){b("#djDebugToolbar").show("fast")}else{b("#djDebugToolbar").show()}b.cookie(d,null,{path:"/",expires:-1})},toggle_arrow:function(f){var e=String.fromCharCode(9654);var g=String.fromCharCode(9660);f.html(f.html()==e?g:e)}};b(document).ready(function(){c.init()})});
\ No newline at end of file
+(function(g,a,b,i){var f,h;var e=false;if(!(f=g.jQuery)||b>f.fn.jquery||i(f)){var c=a.createElement("script");c.type="text/javascript";c.src=DEBUG_TOOLBAR_MEDIA_URL+"js/jquery.js";c.onload=c.onreadystatechange=function(){if(!e&&(!(h=this.readyState)||h=="loaded"||h=="complete")){i((f=g.jQuery).noConflict(1),e=true);f(c).remove()}};a.documentElement.childNodes[0].appendChild(c)}})(window,document,"1.3",function(d,c){d.cookie=function(h,p,s){if(typeof p!="undefined"){s=s||{};if(p===null){p="";s.expires=-1}var l="";if(s.expires&&(typeof s.expires=="number"||s.expires.toUTCString)){var m;if(typeof s.expires=="number"){m=new Date();m.setTime(m.getTime()+(s.expires*24*60*60*1000))}else{m=s.expires}l="; expires="+m.toUTCString()}var r=s.path?"; path="+(s.path):"";var n=s.domain?"; domain="+(s.domain):"";var g=s.secure?"; secure":"";document.cookie=[h,"=",encodeURIComponent(p),l,r,n,g].join("")}else{var k=null;if(document.cookie&&document.cookie!=""){var q=document.cookie.split(";");for(var o=0;o ');var f="djdt";var e={init:function(){d("#djDebug").show();var g=null;d("#djDebugPanelList li a").click(function(){if(!this.className){return false}g=d("#djDebug #"+this.className);if(g.is(":visible")){d(document).trigger("close.djDebug");d(this).parent().removeClass("active")}else{d(".panelContent").hide();g.show();d("#djDebugToolbar li").removeClass("active");d(this).parent().addClass("active")}return false});d("#djDebug a.djDebugClose").click(function(){d(document).trigger("close.djDebug");d("#djDebugToolbar li").removeClass("active");return false});d("#djDebug a.remoteCall").click(function(){d("#djDebugWindow").load(this.href,function(i,h,k){if(h=="error"){var j='Back '+k.status+": "+k.statusText+" ";d("#djDebugWindow").html(j)}d("#djDebugWindow a.djDebugBack").click(function(){d(this).parent().parent().hide();return false})});d("#djDebugWindow").show();return false});d("#djDebugTemplatePanel a.djTemplateShowContext").click(function(){e.toggle_arrow(d(this).children(".toggleArrow"));e.toggle_content(d(this).parent().next());return false});d("#djDebugSQLPanel a.djSQLShowStacktrace").click(function(){e.toggle_content(d(".djSQLHideStacktraceDiv",d(this).parents("tr")));return false});d("#djHideToolBarButton").click(function(){e.hide_toolbar(true);return false});d("#djShowToolBarButton").click(function(){e.show_toolbar();return false});d(".handle-position").click(function(){d(".repr-info-sel").removeClass("repr-info-sel");d(this).parent().parent().addClass("repr-info-sel");var m=d(this).text();var j=new RegExp("line\\s+([0-9]+)");var i=m.match(j);try{var l=i[1]}catch(k){return}var h=d(document).data("reprlineselpos")||null;if(h){h.removeClass("repr-line-sel")}d(".repr-line-"+l).addClass("repr-line-sel");d(document).data("reprlineselpos",d(".repr-line-"+l));location=location+"#repr-line-"+l});d(document).bind("close.djDebug",function(){if(d("#djDebugWindow").is(":visible")){d("#djDebugWindow").hide();return}if(d(".panelContent").is(":visible")){d(".panelContent").hide();return}if(d("#djDebugToolbar").is(":visible")){e.hide_toolbar(true);return}});if(d.cookie(f)){e.hide_toolbar(false)}else{e.show_toolbar(false)}},toggle_content:function(g){if(g.is(":visible")){g.hide()}else{g.show()}},close:function(){d(document).trigger("close.djDebug");return false},hide_toolbar:function(g){d("#djDebugWindow").hide();d(".panelContent").hide();d("#djDebugToolbar li").removeClass("active");d("#djDebugToolbar").hide("fast");d("#djDebugToolbarHandle").show();d(document).unbind("keydown.djDebug");if(g){d.cookie(f,"hide",{path:"/",expires:10})}},show_toolbar:function(g){d(document).bind("keydown.djDebug",function(h){if(h.keyCode==27){e.close()}});d("#djDebugToolbarHandle").hide();if(g){d("#djDebugToolbar").show("fast")}else{d("#djDebugToolbar").show()}d.cookie(f,null,{path:"/",expires:-1})},toggle_arrow:function(h){var g=String.fromCharCode(9654);var i=String.fromCharCode(9660);h.html(h.html()==g?i:g)}};d(document).ready(function(){e.init()})});
\ No newline at end of file
diff --git a/debug_toolbar/panels/htmlvalidator.py b/debug_toolbar/panels/htmlvalidator.py
new file mode 100644
index 000000000..a5599180e
--- /dev/null
+++ b/debug_toolbar/panels/htmlvalidator.py
@@ -0,0 +1,92 @@
+import re
+
+try:
+ from tidylib import tidy_document
+except ImportError:
+ raise ImportError("""Please, make sure that PyTidyLib
+ module installed - it's required for HTMLValidationDebugPanel""")
+
+from django.template.loader import render_to_string
+from django.utils.translation import ugettext_lazy as _
+from django.utils.safestring import mark_safe
+
+from debug_toolbar.panels import DebugPanel
+
+
+class HTMLValidationDebugPanel(DebugPanel):
+ name = "HTMLValidator"
+ has_content = True
+
+ log_data = None
+ errors_count = 0
+ warns_count = 0
+ src_content = ''
+
+ def nav_title(self):
+ return _("HTML Validator")
+
+ def nav_subtitle(self):
+ return mark_safe(_(u"Tidy Errors: %(errors_cnt)d "\
+ u"Warnings: %(warns_cnt)d") % {
+ 'errors_cnt': self.errors_count,
+ 'warns_cnt': self.warns_count,
+ })
+
+ def title(self):
+ return _("HTML Validator")
+
+ def url(self):
+ return ''
+
+ def process_response(self, request, response):
+ document, errors = tidy_document(response.content,
+ options={'numeric-entities': 1})
+ self.log_data = (document, errors)
+ self.src_content = response.content
+ errors_list = errors.split('\n')
+ self.errors_count = len([err for err in errors_list \
+ if 'error:' in err.lower()])
+ self.warns_count = len([err for err in errors_list \
+ if 'warning:' in err.lower()])
+
+ return response
+
+ def appearance(self, errors):
+ replacements = [
+ (re.compile(r'\<([^\>]*)\>'), \
+ '<\\1> '),
+ (re.compile(r'(line[^\-]*)(.*)'), \
+ u'\\1 \\2 '),
+ (re.compile(r'\s*\-\s+(Error\:|Warning\:)', re.I), \
+ u'\\1 '),
+ ]
+
+ for rx, rp in replacements:
+ errors = re.sub(rx, rp, errors)
+
+ errors_list = errors.split('\n')
+ errors_rt = []
+ # mark lines with error with validation-error class
+ for err in errors_list:
+ if 'error:' in err.lower():
+ err = err.replace(' ', ' ')
+ errors_rt.append(err)
+ continue
+ errors_rt.append(err)
+
+ return errors_rt
+
+ def content(self):
+ context = self.context.copy()
+
+ document, errors = self.log_data
+ lines = self.src_content.split("\n")
+
+ context.update({
+ 'document': document,
+ 'lines': zip(range(1, len(lines) + 1), lines),
+ 'errors': self.appearance(errors),
+ })
+
+ return render_to_string(\
+ 'debug_toolbar/panels/htmlvalidator.html', context)
diff --git a/debug_toolbar/templates/debug_toolbar/base.html b/debug_toolbar/templates/debug_toolbar/base.html
index 7f7a535c9..9880f7ee1 100644
--- a/debug_toolbar/templates/debug_toolbar/base.html
+++ b/debug_toolbar/templates/debug_toolbar/base.html
@@ -2,9 +2,14 @@
+{% if not DEBUG_TOOLBAR_DEV %}
+{% else %}
+
+{% endif %}