diff options
| author | Aymeric Augustin | 2013-11-15 21:41:39 +0100 |
|---|---|---|
| committer | Aymeric Augustin | 2013-11-15 21:42:14 +0100 |
| commit | a5e26bcf0b6d83829a4921fb8f10bdf85727489f (patch) | |
| tree | d64a698f96ba6c7b6f5b8e7288bef77b24e69525 /debug_toolbar | |
| parent | e89992a951b05b20dcd5c59927041d41b23110c9 (diff) | |
| download | django-debug-toolbar-a5e26bcf0b6d83829a4921fb8f10bdf85727489f.tar.bz2 | |
Move panel-specific views in panel modules.
Diffstat (limited to 'debug_toolbar')
| -rw-r--r-- | debug_toolbar/panels/sql.py | 111 | ||||
| -rw-r--r-- | debug_toolbar/panels/template.py | 47 | ||||
| -rw-r--r-- | debug_toolbar/views.py | 160 |
3 files changed, 156 insertions, 162 deletions
diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql.py index 8042269..226778b 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql.py @@ -5,7 +5,10 @@ from copy import copy from django.conf.urls import patterns, url from django.db import connections +from django.http import HttpResponseBadRequest +from django.shortcuts import render from django.utils.translation import ugettext_lazy as _, ungettext_lazy as __ +from django.views.decorators.csrf import csrf_exempt from debug_toolbar.forms import SQLSelectForm from debug_toolbar.panels import DebugPanel @@ -106,7 +109,7 @@ class SQLDebugPanel(DebugPanel): @classmethod def get_urls(cls): - return patterns('debug_toolbar.views', # noqa + return patterns('debug_toolbar.panels.sql', # noqa url(r'^sql_select/$', 'sql_select', name='sql_select'), url(r'^sql_explain/$', 'sql_explain', name='sql_explain'), url(r'^sql_profile/$', 'sql_profile', name='sql_profile'), @@ -208,3 +211,109 @@ class SQLDebugPanel(DebugPanel): 'queries': [q for a, q in self._queries], 'sql_time': self._sql_time, }) + + +@csrf_exempt +def sql_select(request): + """Returns the output of the SQL SELECT statement""" + form = SQLSelectForm(request.POST or None) + + if form.is_valid(): + sql = form.cleaned_data['raw_sql'] + params = form.cleaned_data['params'] + cursor = form.cursor + cursor.execute(sql, params) + headers = [d[0] for d in cursor.description] + result = cursor.fetchall() + cursor.close() + context = { + 'result': result, + 'sql': form.reformat_sql(), + 'duration': form.cleaned_data['duration'], + 'headers': headers, + 'alias': form.cleaned_data['alias'], + } + return render(request, 'debug_toolbar/panels/sql_select.html', context) + return HttpResponseBadRequest('Form errors') + + +@csrf_exempt +def sql_explain(request): + """Returns the output of the SQL EXPLAIN on the given query""" + form = SQLSelectForm(request.POST or None) + + if form.is_valid(): + sql = form.cleaned_data['raw_sql'] + params = form.cleaned_data['params'] + cursor = form.cursor + + conn = form.connection + engine = conn.__class__.__module__.split('.', 1)[0] + + if engine == "sqlite3": + # SQLite's EXPLAIN dumps the low-level opcodes generated for a query; + # EXPLAIN QUERY PLAN dumps a more human-readable summary + # See http://www.sqlite.org/lang_explain.html for details + cursor.execute("EXPLAIN QUERY PLAN %s" % (sql,), params) + elif engine == "psycopg2": + cursor.execute("EXPLAIN ANALYZE %s" % (sql,), params) + else: + cursor.execute("EXPLAIN %s" % (sql,), params) + + headers = [d[0] for d in cursor.description] + result = cursor.fetchall() + cursor.close() + context = { + 'result': result, + 'sql': form.reformat_sql(), + 'duration': form.cleaned_data['duration'], + 'headers': headers, + 'alias': form.cleaned_data['alias'], + } + return render(request, 'debug_toolbar/panels/sql_explain.html', context) + return HttpResponseBadRequest('Form errors') + + +@csrf_exempt +def sql_profile(request): + """Returns the output of running the SQL and getting the profiling statistics""" + form = SQLSelectForm(request.POST or None) + + if form.is_valid(): + sql = form.cleaned_data['raw_sql'] + params = form.cleaned_data['params'] + cursor = form.cursor + result = None + headers = None + result_error = None + try: + cursor.execute("SET PROFILING=1") # Enable profiling + cursor.execute(sql, params) # Execute SELECT + cursor.execute("SET PROFILING=0") # Disable profiling + # The Query ID should always be 1 here but I'll subselect to get + # the last one just in case... + cursor.execute(""" + SELECT * + FROM information_schema.profiling + WHERE query_id = ( + SELECT query_id + FROM information_schema.profiling + ORDER BY query_id DESC + LIMIT 1 + ) +""") + headers = [d[0] for d in cursor.description] + result = cursor.fetchall() + except Exception: + result_error = "Profiling is either not available or not supported by your database." + cursor.close() + context = { + 'result': result, + 'result_error': result_error, + 'sql': form.reformat_sql(), + 'duration': form.cleaned_data['duration'], + 'headers': headers, + 'alias': form.cleaned_data['alias'], + } + return render(request, 'debug_toolbar/panels/sql_profile.html', context) + return HttpResponseBadRequest('Form errors') diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template.py index 562e87f..e21cc9e 100644 --- a/debug_toolbar/panels/template.py +++ b/debug_toolbar/panels/template.py @@ -5,12 +5,16 @@ from pprint import pformat import django from django import http +from django.http import HttpResponseBadRequest from django.conf import settings from django.conf.urls import patterns, url from django.db.models.query import QuerySet, RawQuerySet +from django.shortcuts import render +from django.template import TemplateDoesNotExist from django.template.context import get_standard_processors from django.test.signals import template_rendered from django.utils.encoding import force_text +from django.utils.safestring import mark_safe from django.utils import six from django.utils.translation import ugettext_lazy as _ @@ -116,8 +120,8 @@ class TemplateDebugPanel(DebugPanel): @classmethod def get_urls(cls): - return patterns('debug_toolbar.views', # noqa - url(r'^template_source/$', 'template_source', name='template_source'), + return patterns('debug_toolbar.panels.template', # noqa + url(r'^template_source/$', template_source, name='template_source'), ) def nav_title(self): @@ -157,3 +161,42 @@ class TemplateDebugPanel(DebugPanel): 'template_dirs': [normpath(x) for x in settings.TEMPLATE_DIRS], 'context_processors': context_processors, }) + + +def template_source(request): + """ + Return the source of a template, syntax-highlighted by Pygments if + it's available. + """ + template_name = request.GET.get('template', None) + if template_name is None: + return HttpResponseBadRequest('"template" key is required') + + from django.template.loader import find_template_loader + loaders = [] + for loader_name in settings.TEMPLATE_LOADERS: + loader = find_template_loader(loader_name) + if loader is not None: + loaders.append(loader) + for loader in loaders: + try: + source, display_name = loader.load_template_source(template_name) + break + except TemplateDoesNotExist: + source = "Template Does Not Exist: %s" % (template_name,) + + try: + from pygments import highlight + from pygments.lexers import HtmlDjangoLexer + from pygments.formatters import HtmlFormatter + + source = highlight(source, HtmlDjangoLexer(), HtmlFormatter()) + source = mark_safe(source) + source.pygmentized = True + except ImportError: + pass + + return render(request, 'debug_toolbar/panels/template_source.html', { + 'source': source, + 'template_name': template_name + }) diff --git a/debug_toolbar/views.py b/debug_toolbar/views.py index 841d04e..5d41f77 100644 --- a/debug_toolbar/views.py +++ b/debug_toolbar/views.py @@ -1,18 +1,9 @@ -""" -Helper views for the debug toolbar. These are dynamically installed when the -debug toolbar is displayed, and typically can do Bad Things, so hooking up these -views in any other way is generally not advised. -""" - from __future__ import unicode_literals -from django.http import HttpResponse, HttpResponseBadRequest -from django.shortcuts import render +from django.http import HttpResponse from django.utils.html import escape from django.utils.translation import ugettext as _ -from django.views.decorators.csrf import csrf_exempt -from debug_toolbar.forms import SQLSelectForm from debug_toolbar.toolbar import DebugToolbar @@ -30,152 +21,3 @@ def render_panel(request): content = panel.content() break return HttpResponse(content) - - -@csrf_exempt -def sql_select(request): - """Returns the output of the SQL SELECT statement""" - form = SQLSelectForm(request.POST or None) - - if form.is_valid(): - sql = form.cleaned_data['raw_sql'] - params = form.cleaned_data['params'] - cursor = form.cursor - cursor.execute(sql, params) - headers = [d[0] for d in cursor.description] - result = cursor.fetchall() - cursor.close() - context = { - 'result': result, - 'sql': form.reformat_sql(), - 'duration': form.cleaned_data['duration'], - 'headers': headers, - 'alias': form.cleaned_data['alias'], - } - return render(request, 'debug_toolbar/panels/sql_select.html', context) - return HttpResponseBadRequest('Form errors') - - -@csrf_exempt -def sql_explain(request): - """Returns the output of the SQL EXPLAIN on the given query""" - form = SQLSelectForm(request.POST or None) - - if form.is_valid(): - sql = form.cleaned_data['raw_sql'] - params = form.cleaned_data['params'] - cursor = form.cursor - - conn = form.connection - engine = conn.__class__.__module__.split('.', 1)[0] - - if engine == "sqlite3": - # SQLite's EXPLAIN dumps the low-level opcodes generated for a query; - # EXPLAIN QUERY PLAN dumps a more human-readable summary - # See http://www.sqlite.org/lang_explain.html for details - cursor.execute("EXPLAIN QUERY PLAN %s" % (sql,), params) - elif engine == "psycopg2": - cursor.execute("EXPLAIN ANALYZE %s" % (sql,), params) - else: - cursor.execute("EXPLAIN %s" % (sql,), params) - - headers = [d[0] for d in cursor.description] - result = cursor.fetchall() - cursor.close() - context = { - 'result': result, - 'sql': form.reformat_sql(), - 'duration': form.cleaned_data['duration'], - 'headers': headers, - 'alias': form.cleaned_data['alias'], - } - return render(request, 'debug_toolbar/panels/sql_explain.html', context) - return HttpResponseBadRequest('Form errors') - - -@csrf_exempt -def sql_profile(request): - """Returns the output of running the SQL and getting the profiling statistics""" - form = SQLSelectForm(request.POST or None) - - if form.is_valid(): - sql = form.cleaned_data['raw_sql'] - params = form.cleaned_data['params'] - cursor = form.cursor - result = None - headers = None - result_error = None - try: - cursor.execute("SET PROFILING=1") # Enable profiling - cursor.execute(sql, params) # Execute SELECT - cursor.execute("SET PROFILING=0") # Disable profiling - # The Query ID should always be 1 here but I'll subselect to get - # the last one just in case... - cursor.execute(""" - SELECT * - FROM information_schema.profiling - WHERE query_id = ( - SELECT query_id - FROM information_schema.profiling - ORDER BY query_id DESC - LIMIT 1 - ) -""") - headers = [d[0] for d in cursor.description] - result = cursor.fetchall() - except Exception: - result_error = "Profiling is either not available or not supported by your database." - cursor.close() - context = { - 'result': result, - 'result_error': result_error, - 'sql': form.reformat_sql(), - 'duration': form.cleaned_data['duration'], - 'headers': headers, - 'alias': form.cleaned_data['alias'], - } - return render(request, 'debug_toolbar/panels/sql_profile.html', context) - return HttpResponseBadRequest('Form errors') - - -def template_source(request): - """ - Return the source of a template, syntax-highlighted by Pygments if - it's available. - """ - from django.template import TemplateDoesNotExist - from django.utils.safestring import mark_safe - from django.conf import settings - - template_name = request.GET.get('template', None) - if template_name is None: - return HttpResponseBadRequest('"template" key is required') - - from django.template.loader import find_template_loader - loaders = [] - for loader_name in settings.TEMPLATE_LOADERS: - loader = find_template_loader(loader_name) - if loader is not None: - loaders.append(loader) - for loader in loaders: - try: - source, display_name = loader.load_template_source(template_name) - break - except TemplateDoesNotExist: - source = "Template Does Not Exist: %s" % (template_name,) - - try: - from pygments import highlight - from pygments.lexers import HtmlDjangoLexer - from pygments.formatters import HtmlFormatter - - source = highlight(source, HtmlDjangoLexer(), HtmlFormatter()) - source = mark_safe(source) - source.pygmentized = True - except ImportError: - pass - - return render(request, 'debug_toolbar/panels/template_source.html', { - 'source': source, - 'template_name': template_name - }) |
