Converted sql_queries into a lazily evaluated list.

Fixed #23364. Thanks Markush2010 for the report.
This commit is contained in:
Bas Peschier 2014-08-27 10:41:12 +02:00 committed by Aymeric Augustin
parent 6613ea6e3f
commit eacf244506
7 changed files with 71 additions and 4 deletions

View File

@ -35,12 +35,16 @@ def csrf(request):
def debug(request):
"Returns context variables helpful for debugging."
"""
Returns context variables helpful for debugging.
"""
context_extras = {}
if settings.DEBUG and request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
context_extras['debug'] = True
from django.db import connection
context_extras['sql_queries'] = connection.queries
# Return a lazy reference that computes connection.queries on access,
# to ensure it contains queries triggered after this function runs.
context_extras['sql_queries'] = lazy(lambda: connection.queries, list)
return context_extras

View File

@ -555,7 +555,8 @@ If :setting:`TEMPLATE_CONTEXT_PROCESSORS` contains this processor, every
you're in :setting:`DEBUG` mode.
* ``sql_queries`` -- A list of ``{'sql': ..., 'time': ...}`` dictionaries,
representing every SQL query that has happened so far during the request
and how long it took. The list is in order by query.
and how long it took. The list is in order by query and lazily generated
on access.
django.core.context_processors.i18n
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

View File

@ -0,0 +1,5 @@
from django.db import models
class DebugObject(models.Model):
pass

View File

@ -0,0 +1,15 @@
{% if debug == True %}
Have debug
First query list: {{ sql_queries|length }}
{% for obj in debug_objects.all %}{{ obj }}{% endfor %}
Second query list: {{ sql_queries|length }}
{% for obj in debug_objects.all %}{{ obj }}{% endfor %}
Third query list: {{ sql_queries|length }}
{% endif %}

View File

@ -33,3 +33,33 @@ class RequestContextProcessorTests(TestCase):
self.assertContains(response, url)
response = self.client.post(url, {'path': '/blah/'})
self.assertContains(response, url)
@override_settings(ROOT_URLCONF='context_processors.urls', DEBUG=True, INTERNAL_IPS=('127.0.0.1',))
class DebugContextProcessorTests(TestCase):
"""
Tests for the ``django.core.context_processors.debug`` processor.
"""
def test_debug(self):
url = '/debug/'
# We should have the debug flag in the template.
response = self.client.get(url)
self.assertContains(response, 'Have debug')
# And now we should not
with override_settings(DEBUG=False):
response = self.client.get(url)
self.assertNotContains(response, 'Have debug')
def test_sql_queries(self):
"""
Test whether sql_queries represents the actual amount
of queries executed. (#23364)
"""
url = '/debug/'
response = self.client.get(url)
self.assertContains(response, 'First query list: 0')
self.assertContains(response, 'Second query list: 1')
# Check we have not actually memoized connection.queries
self.assertContains(response, 'Third query list: 2')

View File

@ -5,4 +5,5 @@ from . import views
urlpatterns = [
url(r'^request_attrs/$', views.request_processor),
url(r'^debug/$', views.debug_processor),
]

View File

@ -2,7 +2,18 @@ from django.core import context_processors
from django.shortcuts import render_to_response
from django.template.context import RequestContext
from .models import DebugObject
def request_processor(request):
return render_to_response('context_processors/request_attrs.html',
return render_to_response(
'context_processors/request_attrs.html',
RequestContext(request, {}, processors=[context_processors.request]))
def debug_processor(request):
return render_to_response(
'context_processors/debug.html',
RequestContext(request, {
'debug_objects': DebugObject.objects,
}, processors=[context_processors.debug]))