From 84a32968d15f61933115fa059c9037f3356a423d Mon Sep 17 00:00:00 2001 From: Jan Pieter Waagmeester Date: Fri, 22 Dec 2017 19:41:48 +0100 Subject: [PATCH 1/2] Fix missing query-actions buttons for queries with date/datetime params. The param `strings_only=True` caused params with type `time`, `date` and `datetime` to not be converted to string by `NormalCursorWrapper._decode()`, and in turn causes the json dumping to fail. This change keeps `strings_only=True` for every type but datetime, date and time, enabling conversion to string in those cases. Fixes #882 --- debug_toolbar/panels/sql/tracking.py | 7 +++++-- tests/panels/test_sql.py | 31 ++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/debug_toolbar/panels/sql/tracking.py b/debug_toolbar/panels/sql/tracking.py index cf7cae2f5..1751604f8 100644 --- a/debug_toolbar/panels/sql/tracking.py +++ b/debug_toolbar/panels/sql/tracking.py @@ -1,5 +1,6 @@ from __future__ import absolute_import, unicode_literals +import datetime import json from threading import local from time import time @@ -95,8 +96,10 @@ def _quote_params(self, params): return [self._quote_expr(p) for p in params] def _decode(self, param): + # make sure datetime, date and time are converted to string by force_text + CONVERT_TYPES = (datetime.datetime, datetime.date, datetime.time) try: - return force_text(param, strings_only=True) + return force_text(param, strings_only=not isinstance(param, CONVERT_TYPES)) except UnicodeDecodeError: return '(encoded string)' @@ -114,7 +117,7 @@ def _record(self, method, sql, params): _params = '' try: _params = json.dumps([self._decode(p) for p in params]) - except Exception: + except TypeError as e: pass # object not JSON serializable template_info = get_template_info() diff --git a/tests/panels/test_sql.py b/tests/panels/test_sql.py index 886c8f259..d0bc5fbe5 100644 --- a/tests/panels/test_sql.py +++ b/tests/panels/test_sql.py @@ -2,10 +2,12 @@ from __future__ import absolute_import, unicode_literals +import datetime import unittest from django.contrib.auth.models import User from django.db import connection +from django.db.models import Count from django.db.utils import DatabaseError from django.shortcuts import render from django.test.utils import override_settings @@ -69,6 +71,35 @@ def test_non_ascii_query(self): # ensure the panel renders correctly self.assertIn('café', self.panel.content) + def test_param_conversion(self): + self.assertEqual(len(self.panel._queries), 0) + + list( + User.objects + .filter(first_name='Foo') + .filter(is_staff=True) + .filter(is_superuser=False) + ) + list( + User.objects + .annotate(group_count=Count('groups__id')) + .filter(group_count__lt=10) + .filter(group_count__gt=1) + ) + list(User.objects.filter(date_joined=datetime.datetime(2017, 12, 22, 16, 7, 1))) + + self.panel.process_response(self.request, self.response) + self.panel.generate_stats(self.request, self.response) + + # ensure query was logged + self.assertEqual(len(self.panel._queries), 3) + + self.assertEqual(tuple([q[1]['params'] for q in self.panel._queries]), ( + '["Foo", true, false]', + '[10, 1]', + '["2017-12-22 16:07:01"]' + )) + def test_insert_content(self): """ Test that the panel only inserts content after generate_stats and From e75a57934eb2706a0bd8fde9671ae682d0b1bca0 Mon Sep 17 00:00:00 2001 From: Jan Pieter Waagmeester Date: Tue, 23 Jan 2018 09:38:16 +0100 Subject: [PATCH 2/2] Remove unused variable e --- debug_toolbar/panels/sql/tracking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debug_toolbar/panels/sql/tracking.py b/debug_toolbar/panels/sql/tracking.py index 1751604f8..7d07e444e 100644 --- a/debug_toolbar/panels/sql/tracking.py +++ b/debug_toolbar/panels/sql/tracking.py @@ -117,7 +117,7 @@ def _record(self, method, sql, params): _params = '' try: _params = json.dumps([self._decode(p) for p in params]) - except TypeError as e: + except TypeError: pass # object not JSON serializable template_info = get_template_info()