Skip to content

Commit 4c1c4f7

Browse files
committed
Merge branch 'master' of https://github.com/django-debug-toolbar/django-debug-toolbar into sql-panel-refactor
Conflicts: debug_toolbar/static/debug_toolbar/css/toolbar.min.css debug_toolbar/views.py
2 parents 3d0467d + 6f79f0b commit 4c1c4f7

File tree

15 files changed

+145
-48
lines changed

15 files changed

+145
-48
lines changed

.travis.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ python:
33
- "2.6"
44
- "2.7"
55
env:
6-
- DJANGO_VERSION=1.3.1
7-
- DJANGO_VERSION=1.4
6+
- DJANGO_VERSION=1.3.7
7+
- DJANGO_VERSION=1.4.5
8+
- DJANGO_VERSION=1.5
89
install:
910
- pip install Django==$DJANGO_VERSION
1011
- python setup.py install

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# Make file to compress and join all JS files
22
all: compress_js compress_css
33

4+
test:
5+
pip install Django
6+
python runtests.py
7+
48
compress_js:
59
java -jar ~/bin/yuicompressor.jar debug_toolbar/static/debug_toolbar/js/jquery.js > debug_toolbar/static/debug_toolbar/js/toolbar.min.js
610
java -jar ~/bin/yuicompressor.jar debug_toolbar/static/debug_toolbar/js/toolbar.js >> debug_toolbar/static/debug_toolbar/js/toolbar.min.js

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ There is also one Django management command currently:
2929

3030
If you have ideas for other panels please let us know.
3131

32-
* Note: The Debug Toolbar only works on Django 1.2 and newer.
32+
* Note: The Debug Toolbar only works on Django 1.3 and newer.
3333

3434
Installation
3535
============

debug_toolbar/middleware.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ def process_response(self, request, response):
119119
if not toolbar or request.is_ajax():
120120
return response
121121
if isinstance(response, HttpResponseRedirect):
122-
if not toolbar.config['INTERCEPT_REDIRECTS']:
122+
if not toolbar.config['INTERCEPT_REDIRECTS'] or request.is_ajax():
123123
return response
124124
redirect_to = response.get('Location', None)
125125
if redirect_to:

debug_toolbar/panels/template.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from django.template.context import get_standard_processors
77
from django.test.signals import template_rendered
88
from django.utils.translation import ugettext_lazy as _
9-
from django.db.models.query import QuerySet
9+
from django.db.models.query import QuerySet, RawQuerySet
1010
from debug_toolbar.panels import DebugPanel
1111
from debug_toolbar.utils.tracking.db import recording, SQLQueryTriggered
1212

@@ -76,9 +76,9 @@ def _store_template_info(self, sender, **kwargs):
7676
elif key == 'LANGUAGES' and isinstance(value, tuple):
7777
temp_layer[key] = '<<languages>>'
7878
# QuerySet would trigger the database: user can run the query from SQL Panel
79-
elif isinstance(value, QuerySet):
79+
elif isinstance(value, (QuerySet, RawQuerySet)):
8080
model_name = "%s.%s" % (value.model._meta.app_label, value.model.__name__)
81-
temp_layer[key] = '<<queryset of %s>>' % model_name
81+
temp_layer[key] = '<<%s of %s>>' % (value.__class__.__name__.lower(), model_name)
8282
else:
8383
try:
8484
recording(False)

debug_toolbar/static/debug_toolbar/css/toolbar.css

Lines changed: 24 additions & 19 deletions
Large diffs are not rendered by default.

debug_toolbar/urls.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,10 @@
44
These should not be loaded explicitly; the debug toolbar middleware will patch
55
this into the urlconf for the request.
66
"""
7-
from django.conf.urls.defaults import *
7+
try:
8+
from django.conf.urls import patterns, url
9+
except ImportError: # django < 1.4
10+
from django.conf.urls.defaults import patterns, url
811

912
_PREFIX = '__debug__'
1013

debug_toolbar/utils/__init__.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,15 @@ def render_stacktrace(trace):
5656
stacktrace = []
5757
for frame in trace:
5858
params = map(escape, frame[0].rsplit(os.path.sep, 1) + list(frame[1:]))
59+
params_dict = dict((unicode(idx), v) for idx, v in enumerate(params))
5960
try:
60-
stacktrace.append(u'<span class="path">{0}/</span><span class="file">{1}</span> in <span class="func">{3}</span>(<span class="lineno">{2}</span>)\n <span class="code">{4}</span>'.format(*params))
61-
except IndexError:
61+
stacktrace.append(u'<span class="path">%(0)s/</span>'
62+
u'<span class="file">%(1)s</span>'
63+
u' in <span class="func">%(3)s</span>'
64+
u'(<span class="lineno">%(2)s</span>)\n'
65+
u' <span class="code">%(4)s</span>'
66+
% params_dict)
67+
except KeyError:
6268
# This frame doesn't have the expected format, so skip it and move on to the next one
6369
continue
6470
return mark_safe('\n'.join(stacktrace))

debug_toolbar/utils/tracking/db.py

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,20 @@
55

66
from django.conf import settings
77
from django.template import Node
8-
from django.utils import simplejson
98
from django.utils.encoding import force_unicode, smart_str
109

1110
from debug_toolbar.utils import ms_from_timedelta, tidy_stacktrace, \
1211
get_template_info, get_stack
1312
from debug_toolbar.utils.compat.db import connections
1413

14+
try:
15+
import json
16+
except ImportError: # python < 2.6
17+
from django.utils import simplejson as json
18+
1519
try:
1620
from hashlib import sha1
17-
except ImportError:
21+
except ImportError: # python < 2.5
1822
from django.utils.hashcompat import sha_constructor as sha1
1923

2024
# TODO:This should be set in the toolbar loader as a default and panels should
@@ -87,12 +91,25 @@ def _quote_params(self, params):
8791
for key, value in params.iteritems())
8892
return map(self._quote_expr, params)
8993

94+
def _decode(self, param):
95+
try:
96+
return force_unicode(param, strings_only=True)
97+
except UnicodeDecodeError:
98+
return '(encoded string)'
99+
90100
def execute(self, sql, params=()):
91-
__traceback_hide__ = True
92101
start = datetime.now()
93102
try:
94103
return self.cursor.execute(sql, params)
95104
finally:
105+
# FIXME: Sometimes connections which are not in the connections
106+
# dict are used (for example in test database destroying).
107+
# The code below (at least get_transaction_id(alias) needs to have
108+
# the connection in the connections dict. It would be good to
109+
# not have this requirement at all, but for now lets just skip
110+
# these connections.
111+
if self.db.alias not in connections:
112+
return
96113
stop = datetime.now()
97114
duration = ms_from_timedelta(stop - start)
98115
enable_stacktraces = getattr(settings,
@@ -103,10 +120,8 @@ def execute(self, sql, params=()):
103120
stacktrace = []
104121
_params = ''
105122
try:
106-
_params = simplejson.dumps(
107-
[force_unicode(x, strings_only=True) for x in params]
108-
)
109-
except TypeError:
123+
_params = json.dumps(map(self._decode, params))
124+
except Exception:
110125
pass # object not JSON serializable
111126

112127
template_info = None
@@ -124,7 +139,7 @@ def execute(self, sql, params=()):
124139
del cur_frame
125140

126141
alias = getattr(self.db, 'alias', 'default')
127-
conn = connections[alias].connection
142+
conn = self.db.connection
128143
# HACK: avoid imports
129144
if conn:
130145
engine = conn.__class__.__module__.split('.', 1)[0]
@@ -148,11 +163,17 @@ def execute(self, sql, params=()):
148163
}
149164

150165
if engine == 'psycopg2':
151-
from psycopg2.extensions import TRANSACTION_STATUS_INERROR
166+
# If an erroneous query was ran on the connection, it might
167+
# be in a state where checking isolation_level raises an
168+
# exception.
169+
try:
170+
iso_level = conn.isolation_level
171+
except conn.InternalError:
172+
iso_level = 'unknown'
152173
params.update({
153174
'trans_id': self.logger.get_transaction_id(alias),
154175
'trans_status': conn.get_transaction_status(),
155-
'iso_level': conn.isolation_level if not conn.get_transaction_status() == TRANSACTION_STATUS_INERROR else "",
176+
'iso_level': iso_level,
156177
'encoding': conn.encoding,
157178
})
158179

debug_toolbar/views.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,14 @@
88
from django.shortcuts import render_to_response
99
from django.views.decorators.csrf import csrf_exempt
1010

11+
try:
12+
import json
13+
except ImportError: # python < 2.6
14+
from django.utils import simplejson as json
15+
1116
try:
1217
from hashlib import sha1
13-
except ImportError:
18+
except ImportError: # python < 2.5
1419
from django.utils.hashcompat import sha_constructor as sha1
1520

1621
from debug_toolbar.forms import SQLSelectForm
@@ -58,6 +63,8 @@ def sql_explain(request):
5863
# EXPLAIN QUERY PLAN dumps a more human-readable summary
5964
# See http://www.sqlite.org/lang_explain.html for details
6065
cursor.execute("EXPLAIN QUERY PLAN %s" % (sql,), params)
66+
elif engine == "psycopg2":
67+
cursor.execute("EXPLAIN ANALYZE %s" % (sql,), params)
6168
else:
6269
cursor.execute("EXPLAIN %s" % (sql,), params)
6370

0 commit comments

Comments
 (0)