Skip to content

Commit a01d01f

Browse files
committed
Updated patch, debug.html and ietf.css for improved sql debug info.
- Legacy-Id: 13204
1 parent 4efe4fc commit a01d01f

3 files changed

Lines changed: 50 additions & 41 deletions

File tree

ietf/static/ietf/css/ietf.css

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -829,17 +829,28 @@ blockquote {
829829
width: 90%;
830830
}
831831

832-
#debug-query-table .code {
833-
background-color: #eee;
832+
#debug-query-table .origin {
834833
font-family: 'PT Mono', monospace;
835834
font-size: 0.8em;
836835
word-break: break-all;
837836
}
838837

839-
#debug-query-table table {
838+
#debug-query-table .code {
839+
background-color: #eee;
840+
}
841+
842+
#debug-query-table .code td {
843+
white-space: pre;
844+
}
845+
846+
#debug-query-table .table {
840847
max-width: 100%;
841848
}
842849

843850
#debug-query-table .sql {
844851
border-top: 1px solid #555;
845852
}
853+
854+
#debug-query-table .code .current {
855+
background-color: #ddd;
856+
}

ietf/templates/debug.html

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,16 @@ <h4 class="modal-title" id="modal-title-{{forloop.counter}}">QuerySet Origin for
5757
<tbody>
5858
{% if query.origin %}
5959
{% for origin in query.origin %}
60-
<tr class="code">
60+
<tr class="origin">
6161
<td>{{ origin.1 }}({{ origin.2 }})</td>
6262
<td>{{ origin.6 }}()</td>
63-
<td>{{ origin.4.0 }}</td>
63+
<td class="code">
64+
{% for l in origin.4 %}
65+
<table>
66+
<tr><td class="{% if forloop.counter0 == origin.5 %} current{% endif %}">&nbsp;{{l}}</td></tr>
67+
</table>
68+
{% endfor %}
69+
</td>
6470
</tr>
6571
{% endfor %}
6672
{% endif %}

patch/trace-django-queryset-origin.patch

Lines changed: 28 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,30 @@
11
--- ../x/env/lib/python2.7/site-packages/django/db/models/query.py 2017-04-07 15:10:29.426831000 -0700
2-
+++ env/lib/python2.7/site-packages/django/db/models/query.py 2017-04-07 15:18:39.938521412 -0700
3-
@@ -5,6 +5,8 @@
2+
+++ env/lib/python2.7/site-packages/django/db/models/query.py 2017-04-12 08:23:20.061651277 -0700
3+
@@ -5,6 +5,7 @@
44
import copy
55
import sys
66
import warnings
77
+import inspect
8-
+import logging
98
from collections import OrderedDict, deque
109

1110
from django.conf import settings
12-
@@ -34,6 +36,7 @@
11+
@@ -34,7 +35,6 @@
1312
# Pull into this namespace for backwards compatibility.
1413
EmptyResultSet = sql.EmptyResultSet
1514

16-
+logger = logging.getLogger('django.db.backends')
17-
15+
-
1816
class BaseIterable(object):
1917
def __init__(self, queryset):
20-
@@ -51,6 +54,7 @@
18+
self.queryset = queryset
19+
@@ -51,6 +51,7 @@
2120
compiler = queryset.query.get_compiler(using=db)
2221
# Execute the query. This will also fill compiler.select, klass_info,
2322
# and annotations.
2423
+
2524
results = compiler.execute_sql()
2625
select, klass_info, annotation_col_map = (compiler.select, compiler.klass_info,
2726
compiler.annotation_col_map)
28-
@@ -174,6 +178,8 @@
27+
@@ -174,6 +175,8 @@
2928
self._known_related_objects = {} # {rel_field, {pk: rel_obj}}
3029
self._iterable_class = ModelIterable
3130
self._fields = None
@@ -34,15 +33,16 @@
3433

3534
def as_manager(cls):
3635
# Address the circular dependency between `Queryset` and `Manager`.
37-
@@ -316,6 +322,37 @@
36+
@@ -316,6 +319,31 @@
3837
combined.query.combine(other.query, sql.OR)
3938
return combined
4039

4140
+ def _add_origin(self, depth=1):
41+
+ import debug
4242
+ if settings.DEBUG:
4343
+ # get list of frame records. Each is:
4444
+ # [ frame, filename, lineno, function, code_context, index ]
45-
+ stack = inspect.stack()
45+
+ stack = inspect.stack(5)
4646
+ # caller stack record
4747
+ method = stack[depth][3]
4848
+ # look for the first stack entry which is not from django
@@ -56,138 +56,130 @@
5656
+ if function == 'render' and 'context' in frame.f_locals:
5757
+ that = frame.f_locals['self']
5858
+ if hasattr(that, 'filename'):
59-
+ import debug
6059
+ debug.show('that.filename')
61-
+ self._origin += [stack[0]+(method,), ]
60+
+ origin = stack[0]+(method,)
6261
+ else:
63-
+ self._origin += [stack[2]+(method,), ]
64-
+
65-
+ def _log_origin(self):
66-
+ if settings.DEBUG:
67-
+ self._add_origin(depth=3)
68-
+ for place in self._origin:
69-
+ frame, filename, lineno, function, code_context, index, method = place[:7]
70-
+ logger.debug("QuerySet: %s(%s) in %s: %s()\n %s", filename, lineno, function, method, code_context[index].rstrip())
62+
+ origin = stack[2]+(method,)
63+
+ self._origin.append(origin)
7164
+
7265
####################################
7366
# METHODS THAT DO DATABASE QUERIES #
7467
####################################
75-
@@ -793,6 +830,7 @@
68+
@@ -793,6 +821,7 @@
7669
Returns a new QuerySet instance with the args ANDed to the existing
7770
set.
7871
"""
7972
+ self._add_origin()
8073
return self._filter_or_exclude(False, *args, **kwargs)
8174

8275
def exclude(self, *args, **kwargs):
83-
@@ -800,6 +838,7 @@
76+
@@ -800,6 +829,7 @@
8477
Returns a new QuerySet instance with NOT (args) ANDed to the existing
8578
set.
8679
"""
8780
+ self._add_origin()
8881
return self._filter_or_exclude(True, *args, **kwargs)
8982

9083
def _filter_or_exclude(self, negate, *args, **kwargs):
91-
@@ -824,6 +863,7 @@
84+
@@ -824,6 +854,7 @@
9285
This exists to support framework features such as 'limit_choices_to',
9386
and usually it will be more natural to use other methods.
9487
"""
9588
+ self._add_origin()
9689
if isinstance(filter_obj, Q) or hasattr(filter_obj, 'add_to_query'):
9790
clone = self._clone()
9891
clone.query.add_q(filter_obj)
99-
@@ -836,6 +876,7 @@
92+
@@ -836,6 +867,7 @@
10093
Returns a new QuerySet instance that will select objects with a
10194
FOR UPDATE lock.
10295
"""
10396
+ self._add_origin()
10497
obj = self._clone()
10598
obj._for_write = True
10699
obj.query.select_for_update = True
107-
@@ -855,6 +896,7 @@
100+
@@ -855,6 +887,7 @@
108101
if self._fields is not None:
109102
raise TypeError("Cannot call select_related() after .values() or .values_list()")
110103

111104
+ self._add_origin()
112105
obj = self._clone()
113106
if fields == (None,):
114107
obj.query.select_related = False
115-
@@ -874,6 +916,7 @@
108+
@@ -874,6 +907,7 @@
116109
prefetch is appended to. If prefetch_related(None) is called, the list
117110
is cleared.
118111
"""
119112
+ self._add_origin()
120113
clone = self._clone()
121114
if lookups == (None,):
122115
clone._prefetch_related_lookups = []
123-
@@ -886,6 +929,7 @@
116+
@@ -886,6 +920,7 @@
124117
Return a query set in which the returned objects have been annotated
125118
with extra data or aggregations.
126119
"""
127120
+ self._add_origin()
128121
annotations = OrderedDict() # To preserve ordering of args
129122
for arg in args:
130123
# The default_alias property may raise a TypeError, so we use
131-
@@ -929,6 +973,7 @@
124+
@@ -929,6 +964,7 @@
132125
"""
133126
assert self.query.can_filter(), \
134127
"Cannot reorder a query once a slice has been taken."
135128
+ self._add_origin()
136129
obj = self._clone()
137130
obj.query.clear_ordering(force_empty=False)
138131
obj.query.add_ordering(*field_names)
139-
@@ -940,6 +985,7 @@
132+
@@ -940,6 +976,7 @@
140133
"""
141134
assert self.query.can_filter(), \
142135
"Cannot create distinct fields once a slice has been taken."
143136
+ self._add_origin()
144137
obj = self._clone()
145138
obj.query.add_distinct_fields(*field_names)
146139
return obj
147-
@@ -951,6 +997,7 @@
140+
@@ -951,6 +988,7 @@
148141
"""
149142
assert self.query.can_filter(), \
150143
"Cannot change a query once a slice has been taken"
151144
+ self._add_origin()
152145
clone = self._clone()
153146
clone.query.add_extra(select, select_params, where, params, tables, order_by)
154147
return clone
155-
@@ -959,6 +1006,7 @@
148+
@@ -959,6 +997,7 @@
156149
"""
157150
Reverses the ordering of the QuerySet.
158151
"""
159152
+ self._add_origin()
160153
clone = self._clone()
161154
clone.query.standard_ordering = not clone.query.standard_ordering
162155
return clone
163-
@@ -973,6 +1021,7 @@
156+
@@ -973,6 +1012,7 @@
164157
"""
165158
if self._fields is not None:
166159
raise TypeError("Cannot call defer() after .values() or .values_list()")
167160
+ self._add_origin()
168161
clone = self._clone()
169162
if fields == (None,):
170163
clone.query.clear_deferred_loading()
171-
@@ -992,6 +1041,7 @@
164+
@@ -992,6 +1032,7 @@
172165
# Can only pass None to defer(), not only(), as the rest option.
173166
# That won't stop people trying to do this, so let's be explicit.
174167
raise TypeError("Cannot pass None as an argument to only().")
175168
+ self._add_origin()
176169
clone = self._clone()
177170
clone.query.add_immediate_loading(fields)
178171
return clone
179-
@@ -1078,13 +1128,17 @@
172+
@@ -1078,6 +1119,7 @@
180173
clone._known_related_objects = self._known_related_objects
181174
clone._iterable_class = self._iterable_class
182175
clone._fields = self._fields
183176
+ clone._origin = self._origin
184177

185178
clone.__dict__.update(kwargs)
186179
return clone
187-
180+
@@ -1085,6 +1127,8 @@
188181
def _fetch_all(self):
189182
if self._result_cache is None:
190-
+ self._log_origin()
191183
self._result_cache = list(self.iterator())
192184
+ if settings.DEBUG:
193185
+ connections[self.db].queries_log[-1]['origin'] = self._origin

0 commit comments

Comments
 (0)