Updated patch, debug.html and ietf.css for improved sql debug info.

- Legacy-Id: 13204
This commit is contained in:
Henrik Levkowetz 2017-04-12 18:24:51 +00:00
parent 4efe4fcd50
commit a01d01f8e4
3 changed files with 50 additions and 41 deletions

View file

@ -829,17 +829,28 @@ blockquote {
width: 90%; width: 90%;
} }
#debug-query-table .code { #debug-query-table .origin {
background-color: #eee;
font-family: 'PT Mono', monospace; font-family: 'PT Mono', monospace;
font-size: 0.8em; font-size: 0.8em;
word-break: break-all; word-break: break-all;
} }
#debug-query-table table { #debug-query-table .code {
background-color: #eee;
}
#debug-query-table .code td {
white-space: pre;
}
#debug-query-table .table {
max-width: 100%; max-width: 100%;
} }
#debug-query-table .sql { #debug-query-table .sql {
border-top: 1px solid #555; border-top: 1px solid #555;
} }
#debug-query-table .code .current {
background-color: #ddd;
}

View file

@ -57,10 +57,16 @@
<tbody> <tbody>
{% if query.origin %} {% if query.origin %}
{% for origin in query.origin %} {% for origin in query.origin %}
<tr class="code"> <tr class="origin">
<td>{{ origin.1 }}({{ origin.2 }})</td> <td>{{ origin.1 }}({{ origin.2 }})</td>
<td>{{ origin.6 }}()</td> <td>{{ origin.6 }}()</td>
<td>{{ origin.4.0 }}</td> <td class="code">
{% for l in origin.4 %}
<table>
<tr><td class="{% if forloop.counter0 == origin.5 %} current{% endif %}">&nbsp;{{l}}</td></tr>
</table>
{% endfor %}
</td>
</tr> </tr>
{% endfor %} {% endfor %}
{% endif %} {% endif %}

View file

@ -1,23 +1,22 @@
--- ../x/env/lib/python2.7/site-packages/django/db/models/query.py 2017-04-07 15:10:29.426831000 -0700 --- ../x/env/lib/python2.7/site-packages/django/db/models/query.py 2017-04-07 15:10:29.426831000 -0700
+++ env/lib/python2.7/site-packages/django/db/models/query.py 2017-04-07 15:18:39.938521412 -0700 +++ env/lib/python2.7/site-packages/django/db/models/query.py 2017-04-12 08:23:20.061651277 -0700
@@ -5,6 +5,8 @@ @@ -5,6 +5,7 @@
import copy import copy
import sys import sys
import warnings import warnings
+import inspect +import inspect
+import logging
from collections import OrderedDict, deque from collections import OrderedDict, deque
from django.conf import settings from django.conf import settings
@@ -34,6 +36,7 @@ @@ -34,7 +35,6 @@
# Pull into this namespace for backwards compatibility. # Pull into this namespace for backwards compatibility.
EmptyResultSet = sql.EmptyResultSet EmptyResultSet = sql.EmptyResultSet
+logger = logging.getLogger('django.db.backends') -
class BaseIterable(object): class BaseIterable(object):
def __init__(self, queryset): def __init__(self, queryset):
@@ -51,6 +54,7 @@ self.queryset = queryset
@@ -51,6 +51,7 @@
compiler = queryset.query.get_compiler(using=db) compiler = queryset.query.get_compiler(using=db)
# Execute the query. This will also fill compiler.select, klass_info, # Execute the query. This will also fill compiler.select, klass_info,
# and annotations. # and annotations.
@ -25,7 +24,7 @@
results = compiler.execute_sql() results = compiler.execute_sql()
select, klass_info, annotation_col_map = (compiler.select, compiler.klass_info, select, klass_info, annotation_col_map = (compiler.select, compiler.klass_info,
compiler.annotation_col_map) compiler.annotation_col_map)
@@ -174,6 +178,8 @@ @@ -174,6 +175,8 @@
self._known_related_objects = {} # {rel_field, {pk: rel_obj}} self._known_related_objects = {} # {rel_field, {pk: rel_obj}}
self._iterable_class = ModelIterable self._iterable_class = ModelIterable
self._fields = None self._fields = None
@ -34,15 +33,16 @@
def as_manager(cls): def as_manager(cls):
# Address the circular dependency between `Queryset` and `Manager`. # Address the circular dependency between `Queryset` and `Manager`.
@@ -316,6 +322,37 @@ @@ -316,6 +319,31 @@
combined.query.combine(other.query, sql.OR) combined.query.combine(other.query, sql.OR)
return combined return combined
+ def _add_origin(self, depth=1): + def _add_origin(self, depth=1):
+ import debug
+ if settings.DEBUG: + if settings.DEBUG:
+ # get list of frame records. Each is: + # get list of frame records. Each is:
+ # [ frame, filename, lineno, function, code_context, index ] + # [ frame, filename, lineno, function, code_context, index ]
+ stack = inspect.stack() + stack = inspect.stack(5)
+ # caller stack record + # caller stack record
+ method = stack[depth][3] + method = stack[depth][3]
+ # look for the first stack entry which is not from django + # look for the first stack entry which is not from django
@ -56,23 +56,16 @@
+ if function == 'render' and 'context' in frame.f_locals: + if function == 'render' and 'context' in frame.f_locals:
+ that = frame.f_locals['self'] + that = frame.f_locals['self']
+ if hasattr(that, 'filename'): + if hasattr(that, 'filename'):
+ import debug
+ debug.show('that.filename') + debug.show('that.filename')
+ self._origin += [stack[0]+(method,), ] + origin = stack[0]+(method,)
+ else: + else:
+ self._origin += [stack[2]+(method,), ] + origin = stack[2]+(method,)
+ + self._origin.append(origin)
+ def _log_origin(self):
+ if settings.DEBUG:
+ self._add_origin(depth=3)
+ for place in self._origin:
+ frame, filename, lineno, function, code_context, index, method = place[:7]
+ logger.debug("QuerySet: %s(%s) in %s: %s()\n %s", filename, lineno, function, method, code_context[index].rstrip())
+ +
#################################### ####################################
# METHODS THAT DO DATABASE QUERIES # # METHODS THAT DO DATABASE QUERIES #
#################################### ####################################
@@ -793,6 +830,7 @@ @@ -793,6 +821,7 @@
Returns a new QuerySet instance with the args ANDed to the existing Returns a new QuerySet instance with the args ANDed to the existing
set. set.
""" """
@ -80,7 +73,7 @@
return self._filter_or_exclude(False, *args, **kwargs) return self._filter_or_exclude(False, *args, **kwargs)
def exclude(self, *args, **kwargs): def exclude(self, *args, **kwargs):
@@ -800,6 +838,7 @@ @@ -800,6 +829,7 @@
Returns a new QuerySet instance with NOT (args) ANDed to the existing Returns a new QuerySet instance with NOT (args) ANDed to the existing
set. set.
""" """
@ -88,7 +81,7 @@
return self._filter_or_exclude(True, *args, **kwargs) return self._filter_or_exclude(True, *args, **kwargs)
def _filter_or_exclude(self, negate, *args, **kwargs): def _filter_or_exclude(self, negate, *args, **kwargs):
@@ -824,6 +863,7 @@ @@ -824,6 +854,7 @@
This exists to support framework features such as 'limit_choices_to', This exists to support framework features such as 'limit_choices_to',
and usually it will be more natural to use other methods. and usually it will be more natural to use other methods.
""" """
@ -96,7 +89,7 @@
if isinstance(filter_obj, Q) or hasattr(filter_obj, 'add_to_query'): if isinstance(filter_obj, Q) or hasattr(filter_obj, 'add_to_query'):
clone = self._clone() clone = self._clone()
clone.query.add_q(filter_obj) clone.query.add_q(filter_obj)
@@ -836,6 +876,7 @@ @@ -836,6 +867,7 @@
Returns a new QuerySet instance that will select objects with a Returns a new QuerySet instance that will select objects with a
FOR UPDATE lock. FOR UPDATE lock.
""" """
@ -104,7 +97,7 @@
obj = self._clone() obj = self._clone()
obj._for_write = True obj._for_write = True
obj.query.select_for_update = True obj.query.select_for_update = True
@@ -855,6 +896,7 @@ @@ -855,6 +887,7 @@
if self._fields is not None: if self._fields is not None:
raise TypeError("Cannot call select_related() after .values() or .values_list()") raise TypeError("Cannot call select_related() after .values() or .values_list()")
@ -112,7 +105,7 @@
obj = self._clone() obj = self._clone()
if fields == (None,): if fields == (None,):
obj.query.select_related = False obj.query.select_related = False
@@ -874,6 +916,7 @@ @@ -874,6 +907,7 @@
prefetch is appended to. If prefetch_related(None) is called, the list prefetch is appended to. If prefetch_related(None) is called, the list
is cleared. is cleared.
""" """
@ -120,7 +113,7 @@
clone = self._clone() clone = self._clone()
if lookups == (None,): if lookups == (None,):
clone._prefetch_related_lookups = [] clone._prefetch_related_lookups = []
@@ -886,6 +929,7 @@ @@ -886,6 +920,7 @@
Return a query set in which the returned objects have been annotated Return a query set in which the returned objects have been annotated
with extra data or aggregations. with extra data or aggregations.
""" """
@ -128,7 +121,7 @@
annotations = OrderedDict() # To preserve ordering of args annotations = OrderedDict() # To preserve ordering of args
for arg in args: for arg in args:
# The default_alias property may raise a TypeError, so we use # The default_alias property may raise a TypeError, so we use
@@ -929,6 +973,7 @@ @@ -929,6 +964,7 @@
""" """
assert self.query.can_filter(), \ assert self.query.can_filter(), \
"Cannot reorder a query once a slice has been taken." "Cannot reorder a query once a slice has been taken."
@ -136,7 +129,7 @@
obj = self._clone() obj = self._clone()
obj.query.clear_ordering(force_empty=False) obj.query.clear_ordering(force_empty=False)
obj.query.add_ordering(*field_names) obj.query.add_ordering(*field_names)
@@ -940,6 +985,7 @@ @@ -940,6 +976,7 @@
""" """
assert self.query.can_filter(), \ assert self.query.can_filter(), \
"Cannot create distinct fields once a slice has been taken." "Cannot create distinct fields once a slice has been taken."
@ -144,7 +137,7 @@
obj = self._clone() obj = self._clone()
obj.query.add_distinct_fields(*field_names) obj.query.add_distinct_fields(*field_names)
return obj return obj
@@ -951,6 +997,7 @@ @@ -951,6 +988,7 @@
""" """
assert self.query.can_filter(), \ assert self.query.can_filter(), \
"Cannot change a query once a slice has been taken" "Cannot change a query once a slice has been taken"
@ -152,7 +145,7 @@
clone = self._clone() clone = self._clone()
clone.query.add_extra(select, select_params, where, params, tables, order_by) clone.query.add_extra(select, select_params, where, params, tables, order_by)
return clone return clone
@@ -959,6 +1006,7 @@ @@ -959,6 +997,7 @@
""" """
Reverses the ordering of the QuerySet. Reverses the ordering of the QuerySet.
""" """
@ -160,7 +153,7 @@
clone = self._clone() clone = self._clone()
clone.query.standard_ordering = not clone.query.standard_ordering clone.query.standard_ordering = not clone.query.standard_ordering
return clone return clone
@@ -973,6 +1021,7 @@ @@ -973,6 +1012,7 @@
""" """
if self._fields is not None: if self._fields is not None:
raise TypeError("Cannot call defer() after .values() or .values_list()") raise TypeError("Cannot call defer() after .values() or .values_list()")
@ -168,7 +161,7 @@
clone = self._clone() clone = self._clone()
if fields == (None,): if fields == (None,):
clone.query.clear_deferred_loading() clone.query.clear_deferred_loading()
@@ -992,6 +1041,7 @@ @@ -992,6 +1032,7 @@
# Can only pass None to defer(), not only(), as the rest option. # Can only pass None to defer(), not only(), as the rest option.
# That won't stop people trying to do this, so let's be explicit. # That won't stop people trying to do this, so let's be explicit.
raise TypeError("Cannot pass None as an argument to only().") raise TypeError("Cannot pass None as an argument to only().")
@ -176,7 +169,7 @@
clone = self._clone() clone = self._clone()
clone.query.add_immediate_loading(fields) clone.query.add_immediate_loading(fields)
return clone return clone
@@ -1078,13 +1128,17 @@ @@ -1078,6 +1119,7 @@
clone._known_related_objects = self._known_related_objects clone._known_related_objects = self._known_related_objects
clone._iterable_class = self._iterable_class clone._iterable_class = self._iterable_class
clone._fields = self._fields clone._fields = self._fields
@ -184,10 +177,9 @@
clone.__dict__.update(kwargs) clone.__dict__.update(kwargs)
return clone return clone
@@ -1085,6 +1127,8 @@
def _fetch_all(self): def _fetch_all(self):
if self._result_cache is None: if self._result_cache is None:
+ self._log_origin()
self._result_cache = list(self.iterator()) self._result_cache = list(self.iterator())
+ if settings.DEBUG: + if settings.DEBUG:
+ connections[self.db].queries_log[-1]['origin'] = self._origin + connections[self.db].queries_log[-1]['origin'] = self._origin