diff options
| -rw-r--r-- | debug_toolbar/panels/sql/__init__.py | 1 | ||||
| -rw-r--r-- | debug_toolbar/panels/sql/forms.py (renamed from debug_toolbar/forms.py) | 2 | ||||
| -rw-r--r-- | debug_toolbar/panels/sql/panel.py (renamed from debug_toolbar/panels/sql.py) | 117 | ||||
| -rw-r--r-- | debug_toolbar/panels/sql/tracking.py (renamed from debug_toolbar/utils/tracking/db.py) | 0 | ||||
| -rw-r--r-- | debug_toolbar/panels/sql/utils.py (renamed from debug_toolbar/utils/sql.py) | 0 | ||||
| -rw-r--r-- | debug_toolbar/panels/sql/views.py | 113 | ||||
| -rw-r--r-- | debug_toolbar/panels/template/__init__.py | 1 | ||||
| -rw-r--r-- | debug_toolbar/panels/template/panel.py (renamed from debug_toolbar/panels/template.py) | 49 | ||||
| -rw-r--r-- | debug_toolbar/panels/template/views.py | 46 | ||||
| -rw-r--r-- | debug_toolbar/utils/tracking/__init__.py | 0 | 
10 files changed, 169 insertions, 160 deletions
| diff --git a/debug_toolbar/panels/sql/__init__.py b/debug_toolbar/panels/sql/__init__.py new file mode 100644 index 0000000..90e05cb --- /dev/null +++ b/debug_toolbar/panels/sql/__init__.py @@ -0,0 +1 @@ +from debug_toolbar.panels.sql.panel import SQLDebugPanel                # noqa diff --git a/debug_toolbar/forms.py b/debug_toolbar/panels/sql/forms.py index 4f60c11..c18be0c 100644 --- a/debug_toolbar/forms.py +++ b/debug_toolbar/panels/sql/forms.py @@ -10,7 +10,7 @@ from django.utils.encoding import force_text  from django.utils.functional import cached_property  from django.core.exceptions import ValidationError -from debug_toolbar.utils.sql import reformat_sql +from debug_toolbar.panels.sql.utils import reformat_sql  class SQLSelectForm(forms.Form): diff --git a/debug_toolbar/panels/sql.py b/debug_toolbar/panels/sql/panel.py index 226778b..cb80901 100644 --- a/debug_toolbar/panels/sql.py +++ b/debug_toolbar/panels/sql/panel.py @@ -5,16 +5,13 @@ 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 +from debug_toolbar.panels.sql.forms import SQLSelectForm  from debug_toolbar.utils import render_stacktrace -from debug_toolbar.utils.sql import reformat_sql -from debug_toolbar.utils.tracking.db import CursorWrapper +from debug_toolbar.panels.sql.utils import reformat_sql +from debug_toolbar.panels.sql.tracking import CursorWrapper  def get_isolation_level_display(engine, level): @@ -109,7 +106,7 @@ class SQLDebugPanel(DebugPanel):      @classmethod      def get_urls(cls): -        return patterns('debug_toolbar.panels.sql',                     # noqa +        return patterns('debug_toolbar.panels.sql.views',               # 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'), @@ -211,109 +208,3 @@ 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/utils/tracking/db.py b/debug_toolbar/panels/sql/tracking.py index fd56ff9..fd56ff9 100644 --- a/debug_toolbar/utils/tracking/db.py +++ b/debug_toolbar/panels/sql/tracking.py diff --git a/debug_toolbar/utils/sql.py b/debug_toolbar/panels/sql/utils.py index 00728a3..00728a3 100644 --- a/debug_toolbar/utils/sql.py +++ b/debug_toolbar/panels/sql/utils.py diff --git a/debug_toolbar/panels/sql/views.py b/debug_toolbar/panels/sql/views.py new file mode 100644 index 0000000..346cf6e --- /dev/null +++ b/debug_toolbar/panels/sql/views.py @@ -0,0 +1,113 @@ +from __future__ import unicode_literals + +from django.http import HttpResponseBadRequest +from django.shortcuts import render +from django.views.decorators.csrf import csrf_exempt + +from debug_toolbar.panels.sql.forms import SQLSelectForm + + +@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/__init__.py b/debug_toolbar/panels/template/__init__.py new file mode 100644 index 0000000..d2f595d --- /dev/null +++ b/debug_toolbar/panels/template/__init__.py @@ -0,0 +1 @@ +from debug_toolbar.panels.template.panel import TemplateDebugPanel      # noqa diff --git a/debug_toolbar/panels/template.py b/debug_toolbar/panels/template/panel.py index e21cc9e..7c4b06a 100644 --- a/debug_toolbar/panels/template.py +++ b/debug_toolbar/panels/template/panel.py @@ -5,21 +5,17 @@ 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 _  from debug_toolbar.panels import DebugPanel -from debug_toolbar.utils.tracking.db import recording, SQLQueryTriggered +from debug_toolbar.panels.sql.tracking import recording, SQLQueryTriggered  from debug_toolbar.utils import settings as dt_settings  # Code taken and adapted from Simon Willison and Django Snippets: @@ -120,8 +116,8 @@ class TemplateDebugPanel(DebugPanel):      @classmethod      def get_urls(cls): -        return patterns('debug_toolbar.panels.template',                # noqa -            url(r'^template_source/$', template_source, name='template_source'), +        return patterns('debug_toolbar.panels.template.views',          # noqa +            url(r'^template_source/$', 'template_source', name='template_source'),          )      def nav_title(self): @@ -161,42 +157,3 @@ 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/panels/template/views.py b/debug_toolbar/panels/template/views.py new file mode 100644 index 0000000..30bd167 --- /dev/null +++ b/debug_toolbar/panels/template/views.py @@ -0,0 +1,46 @@ +from __future__ import unicode_literals + +from django.http import HttpResponseBadRequest +from django.conf import settings +from django.shortcuts import render +from django.template import TemplateDoesNotExist +from django.template.loader import find_template_loader +from django.utils.safestring import mark_safe + + +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') + +    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/utils/tracking/__init__.py b/debug_toolbar/utils/tracking/__init__.py deleted file mode 100644 index e69de29..0000000 --- a/debug_toolbar/utils/tracking/__init__.py +++ /dev/null | 
