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" %}

+ + + + + + + + + + + {% for sender, s in stat.iteritems %} + + + + + + + {% endfor %} + +
{% trans "Model" %}{% trans 'Created' %}{% trans 'Changed' %}{% trans 'Deleted' %}
{{ sender }}{{ s.created }}{{ s.updated }}{{ s.deleted }}
+{% endifequal %} + +

{% trans "Objects state" %}

+

+{% trans "C" %} — {% trans "Created" %} +    +{% trans "U" %} — {% trans "Updated" %} +    +{% trans "D" %} — {% trans "Deleted" %} +

+ + + + + + + + + + + + + {% for item in objects_state %} + + + + + + + + + {% endfor %} + +
{% trans "C" %}{% trans "U" %}{% trans "D" %}{% trans "Model" %}{% trans 'Objects amount' %}{% trans 'Previous objects amount' %}
{{ item.created_amount }}{{ item.updated_amount }}{{ item.deleted_amount }}{{ item.model }}{{ item.cur }}{{ item.prev }}
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^=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 %}