Skip to content

Commit 0b809d5

Browse files
Support hiding migrations and models when not using the DatabaseStore (#2236)
* Hide the migrations when not using the database store. This is a bit of a hack as we're adjusting the project's settings and it hides all migrations. * Hide the toolbar's models when the database store isn't used. * Force the tests to always find the toolbar's migrations.
1 parent 45bc2db commit 0b809d5

File tree

6 files changed

+92
-4
lines changed

6 files changed

+92
-4
lines changed

debug_toolbar/apps.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,35 @@ def ready(self):
2424
# allows panels like CachePanel to enable their instrumentation immediately.
2525
for cls in DebugToolbar.get_panel_classes():
2626
cls.ready()
27+
_manage_migrations_visibility(self.name)
28+
29+
def import_models(self):
30+
"""
31+
Override import models to avoid allowing users to dynamically fetch a model
32+
that doesn't have a table behind it unless they are using the DatabaseStore.
33+
This also prevents the command `migrate --run-syncdb` from creating tables
34+
for the models.
35+
"""
36+
dt_config = dt_settings.get_config()
37+
if dt_config["TOOLBAR_STORE_CLASS"] == "debug_toolbar.store.DatabaseStore":
38+
return super().import_models()
39+
# Not using the database store, don't import the models
40+
self.models = {}
41+
42+
43+
def _manage_migrations_visibility(app_name):
44+
"""
45+
Adjust the toolbar's migration visibility by manipulating the
46+
project's settings.
47+
48+
This is a hack since it's manipulating settings.
49+
"""
50+
if (
51+
dt_settings.get_config()["TOOLBAR_STORE_CLASS"]
52+
!= "debug_toolbar.store.DatabaseStore"
53+
):
54+
# This effectively hides the migrations by telling Django they don't exist.
55+
settings.MIGRATION_MODULES.setdefault(app_name, None)
2756

2857

2958
def check_template_config(config):

docs/changes.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ Pending
2020
"Django Debug Toolbar was unable to parse value." when there's a decoding
2121
error.
2222
* Updated docs to show incompatibility with Django Channels.
23+
* Hide the toolbar's migrations unless ``debug_toolbar.store.DatabaseStore``
24+
is being used. This may change in the future.
25+
* Hide ``debug_toolbar.HistoryEntry`` as a model unless
26+
``debug_toolbar.store.DatabaseStore`` is being used. This may change in the
27+
future.
2328

2429
6.0.0 (2025-07-22)
2530
------------------

docs/configuration.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -196,15 +196,15 @@ Toolbar options
196196
The DatabaseStore provides persistence and automatically cleans up old
197197
entries based on the ``RESULTS_CACHE_SIZE`` setting.
198198

199-
Note: For full functionality, DatabaseStore requires migrations for
200-
the debug_toolbar app:
199+
Note: When using ``DatabaseStore`` migrations are required for
200+
the ``debug_toolbar`` app:
201201

202202
.. code-block:: bash
203203
204204
python manage.py migrate debug_toolbar
205205
206-
For the DatabaseStore to work properly, you need to run migrations for the
207-
debug_toolbar app. The migrations create the necessary database table to store
206+
For the ``DatabaseStore`` to work properly, you need to run migrations for the
207+
``debug_toolbar`` app. The migrations create the necessary database table to store
208208
toolbar data.
209209

210210
.. _TOOLBAR_LANGUAGE:

tests/settings.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,10 @@
128128

129129
DEFAULT_AUTO_FIELD = "django.db.models.AutoField"
130130

131+
# Force the MIGRATION_MODULES to always find our migrations.
132+
# See debug_toolbar/apps.py::_manage_migrations_visibility
133+
MIGRATION_MODULES = {"debug_toolbar": "debug_toolbar.migrations"}
134+
131135
# Debug Toolbar configuration
132136

133137
DEBUG_TOOLBAR_CONFIG = {

tests/test_apps.py

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
from unittest.mock import patch
2+
3+
from django.apps import apps
4+
from django.test import SimpleTestCase, override_settings
5+
6+
from debug_toolbar.apps import _manage_migrations_visibility
7+
8+
9+
class AppsTestCase(SimpleTestCase):
10+
@override_settings(
11+
DEBUG_TOOLBAR_CONFIG={
12+
"TOOLBAR_STORE_CLASS": "debug_toolbar.store.DatabaseStore"
13+
}
14+
)
15+
@patch("debug_toolbar.apps.settings.MIGRATION_MODULES")
16+
def test_migrations_are_visible(self, mocked_migration_modules):
17+
_manage_migrations_visibility("debug_toolbar")
18+
self.assertFalse(mocked_migration_modules.setdefault.called)
19+
20+
@override_settings(
21+
DEBUG_TOOLBAR_CONFIG={"TOOLBAR_STORE_CLASS": "debug_toolbar.store.MemoryStore"}
22+
)
23+
@patch("debug_toolbar.apps.settings.MIGRATION_MODULES")
24+
def test_migrations_are_hidden(self, mocked_migration_modules):
25+
_manage_migrations_visibility("debug_toolbar")
26+
mocked_migration_modules.setdefault.assert_called_once_with(
27+
"debug_toolbar", None
28+
)
29+
30+
@override_settings(
31+
DEBUG_TOOLBAR_CONFIG={
32+
"TOOLBAR_STORE_CLASS": "debug_toolbar.store.DatabaseStore"
33+
}
34+
)
35+
def test_models_are_visible(self):
36+
app_config = apps.get_app_config("debug_toolbar")
37+
app_config.import_models()
38+
apps.get_model("debug_toolbar", "HistoryEntry")
39+
40+
@override_settings(
41+
DEBUG_TOOLBAR_CONFIG={"TOOLBAR_STORE_CLASS": "debug_toolbar.store.MemoryStore"}
42+
)
43+
def test_models_are_hidden(self):
44+
app_config = apps.get_app_config("debug_toolbar")
45+
app_config.import_models()
46+
with self.assertRaises(LookupError):
47+
apps.get_model("debug_toolbar", "HistoryEntry")

tests/test_store.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,9 @@ def test_get_store_with_setting(self):
132132
self.assertIs(store.get_store(), StubStore)
133133

134134

135+
@override_settings(
136+
DEBUG_TOOLBAR_CONFIG={"TOOLBAR_STORE_CLASS": "debug_toolbar.store.DatabaseStore"}
137+
)
135138
class DatabaseStoreTestCase(TestCase):
136139
@classmethod
137140
def setUpTestData(cls) -> None:

0 commit comments

Comments
 (0)