diff --git a/debug_toolbar/panels/sql/tracking.py b/debug_toolbar/panels/sql/tracking.py index 45e0c0c17..9a06aead4 100644 --- a/debug_toolbar/panels/sql/tracking.py +++ b/debug_toolbar/panels/sql/tracking.py @@ -5,8 +5,10 @@ from time import perf_counter import django.test.testcases +from django.apps import apps from django.utils.encoding import force_str +from debug_toolbar import settings as dt_settings from debug_toolbar.utils import get_stack_trace, get_template_info try: @@ -28,6 +30,11 @@ allow_sql = contextvars.ContextVar("debug-toolbar-allow-sql", default=True) +DDT_MODELS = { + m._meta.db_table for m in apps.get_app_config("debug_toolbar").get_models() +} + + class SQLQueryTriggered(Exception): """Thrown when template panel triggers a query""" @@ -224,8 +231,13 @@ def _record(self, method, sql, params): } ) - # We keep `sql` to maintain backwards compatibility - self.logger.record(**kwargs) + # Skip tracking for DDT models by default. + # This can be overridden by setting TRACK_DDT_MODELS = True + if dt_settings.get_config()["TRACK_DDT_MODELS"] or not any( + table in sql for table in DDT_MODELS + ): + # We keep `sql` to maintain backwards compatibility + self.logger.record(**kwargs) def callproc(self, procname, params=None): return self._record(super().callproc, procname, params) diff --git a/debug_toolbar/settings.py b/debug_toolbar/settings.py index d6b9003b6..737202be0 100644 --- a/debug_toolbar/settings.py +++ b/debug_toolbar/settings.py @@ -28,6 +28,7 @@ def _is_running_tests(): "ROOT_TAG_EXTRA_ATTRS": "", "SHOW_COLLAPSED": False, "SHOW_TOOLBAR_CALLBACK": "debug_toolbar.middleware.show_toolbar", + "TRACK_DDT_MODELS": False, # Panel options "EXTRA_SIGNALS": [], "ENABLE_STACKTRACES": True, diff --git a/tests/panels/test_sql.py b/tests/panels/test_sql.py index e238bd0d8..add9f3546 100644 --- a/tests/panels/test_sql.py +++ b/tests/panels/test_sql.py @@ -15,6 +15,7 @@ from django.test.utils import override_settings import debug_toolbar.panels.sql.tracking as sql_tracking +from debug_toolbar.models import HistoryEntry from debug_toolbar.panels.sql import SQLPanel try: @@ -33,6 +34,18 @@ def sql_call(*, use_iterator=False): return list(qs) +def sql_call_ddt(): + """Helper function to query one of the DDT models to test tracking of DDT entries.""" + qs = HistoryEntry.objects.all() + return list(qs) + + +async def async_sql_call_ddt(): + """(async) Helper function to query one of the DDT models to test tracking of DDT entries.""" + qs = HistoryEntry.objects.all() + return await sync_to_async(list)(qs) + + async def async_sql_call(*, use_iterator=False): qs = User.objects.all() if use_iterator: @@ -104,6 +117,46 @@ async def test_recording_concurrent_async(self): # ensure the stacktrace is populated self.assertTrue(len(query["stacktrace"]) > 0) + @override_settings(DEBUG_TOOLBAR_CONFIG={"TRACK_DDT_MODELS": True}) + def test_ddt_models_tracked(self): + """test if DDT models are being tracked when the `TRACK_DDT_MODELS` is set to True""" + self.assertEqual(len(self.panel._queries), 0) + + sql_call_ddt() + + # ensure query was logged + self.assertEqual(len(self.panel._queries), 1) + query = self.panel._queries[0] + self.assertTrue(HistoryEntry._meta.db_table in query["sql"]) + + @override_settings(DEBUG_TOOLBAR_CONFIG={"TRACK_DDT_MODELS": True}) + async def test_ddt_models_tracked_async(self): + """(async) test if DDT models are being tracked when the `TRACK_DDT_MODELS` is set to True""" + self.assertEqual(len(self.panel._queries), 0) + + await async_sql_call_ddt() + + # ensure query was logged + self.assertEqual(len(self.panel._queries), 1) + query = self.panel._queries[0] + self.assertTrue(HistoryEntry._meta.db_table in query["sql"]) + + def test_ddt_models_not_tracked(self): + """Tests whether DDt models are not being tracked when the `TRACK_DDT_MODELS` is set to False""" + self.assertEqual(len(self.panel._queries), 0) + + sql_call_ddt() + + self.assertEqual(len(self.panel._queries), 0) + + async def test_ddt_models_not_tracked_async(self): + """(async) Tests whether DDt models are not being tracked when the `TRACK_DDT_MODELS` is set to False""" + self.assertEqual(len(self.panel._queries), 0) + + await async_sql_call_ddt() + + self.assertEqual(len(self.panel._queries), 0) + @unittest.skipUnless( connection.vendor == "postgresql", "Test valid only on PostgreSQL" )