From 88d911d52830c3a576896457305f4a99d01df314 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Wed, 8 Oct 2025 09:43:51 +0900 Subject: [PATCH 1/2] Show cache alias instead of backend repr --- debug_toolbar/panels/cache.py | 21 +++++++++++---------- docs/changes.rst | 2 ++ tests/panels/test_cache.py | 4 ++++ 3 files changed, 17 insertions(+), 10 deletions(-) diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py index d3242d9d9..e6f230735 100644 --- a/debug_toolbar/panels/cache.py +++ b/debug_toolbar/panels/cache.py @@ -30,7 +30,7 @@ ] -def _monkey_patch_method(cache, name): +def _monkey_patch_method(cache, name, alias): original_method = getattr(cache, name) @functools.wraps(original_method) @@ -39,15 +39,15 @@ def wrapper(*args, **kwargs): if panel is None: return original_method(*args, **kwargs) else: - return panel._record_call(cache, name, original_method, args, kwargs) + return panel._record_call(cache, alias, name, original_method, args, kwargs) setattr(cache, name, wrapper) -def _monkey_patch_cache(cache): +def _monkey_patch_cache(cache, alias): if not hasattr(cache, "_djdt_patched"): for name in WRAPPED_CACHE_METHODS: - _monkey_patch_method(cache, name) + _monkey_patch_method(cache, name, alias) cache._djdt_patched = True @@ -95,7 +95,7 @@ def wrapper(self, alias): cache = original_method(self, alias) panel = cls.current_instance() if panel is not None: - _monkey_patch_cache(cache) + _monkey_patch_cache(cache, alias) cache._djdt_panel = panel return cache @@ -138,7 +138,7 @@ def _store_call_info( } ) - def _record_call(self, cache, name, original_method, args, kwargs): + def _record_call(self, cache, alias, name, original_method, args, kwargs): # Some cache backends implement certain cache methods in terms of other cache # methods (e.g. get_or_set() in terms of get() and add()). In order to only # record the calls made directly by the user code, set the cache's _djdt_panel @@ -161,7 +161,7 @@ def _record_call(self, cache, name, original_method, args, kwargs): kwargs=kwargs, trace=get_stack_trace(skip=2), template_info=get_template_info(), - backend=cache, + backend=alias, ) return value @@ -194,9 +194,10 @@ def enable_instrumentation(self): # requests. The monkey patch of CacheHander.create_connection() installed in # the .ready() method will ensure that any new cache connections that get opened # during this request will also be monkey patched. - for cache in caches.all(initialized_only=True): - _monkey_patch_cache(cache) - cache._djdt_panel = self + for alias in caches: + if hasattr(caches._connections, alias): + _monkey_patch_cache(caches[alias], alias) + caches[alias]._djdt_panel = self # Mark this panel instance as the current one for the active thread/async task # context. This will be used by the CacheHander.create_connection() monkey # patch. diff --git a/docs/changes.rst b/docs/changes.rst index 452242279..60c602228 100644 --- a/docs/changes.rst +++ b/docs/changes.rst @@ -63,6 +63,8 @@ Pending conflicts * Added CSS for resetting the height of elements too to avoid problems with global CSS of a website where the toolbar is used. +* Show the cache backend alias instead of the cache instance for each call in + the cache panel. 5.1.0 (2025-03-20) ------------------ diff --git a/tests/panels/test_cache.py b/tests/panels/test_cache.py index 05d9341e6..db4922e28 100644 --- a/tests/panels/test_cache.py +++ b/tests/panels/test_cache.py @@ -154,3 +154,7 @@ def test_generate_server_timing(self): } self.assertEqual(self.panel.get_server_timing_stats(), expected_data) + + def test_backend_alias_is_recorded(self): + cache.cache.get("foo") + self.assertEqual(self.panel.calls[0]["backend"], "default") From 2bc97ab3f3022f3767a7ff5477a941207e4ee724 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Sun, 26 Oct 2025 21:14:15 +1100 Subject: [PATCH 2/2] Address review comments --- debug_toolbar/panels/cache.py | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/debug_toolbar/panels/cache.py b/debug_toolbar/panels/cache.py index e6f230735..3786dee26 100644 --- a/debug_toolbar/panels/cache.py +++ b/debug_toolbar/panels/cache.py @@ -44,11 +44,12 @@ def wrapper(*args, **kwargs): setattr(cache, name, wrapper) -def _monkey_patch_cache(cache, alias): +def _monkey_patch_cache(cache, alias, panel): if not hasattr(cache, "_djdt_patched"): for name in WRAPPED_CACHE_METHODS: _monkey_patch_method(cache, name, alias) cache._djdt_patched = True + cache._djdt_panel = panel class CachePanel(Panel): @@ -95,8 +96,7 @@ def wrapper(self, alias): cache = original_method(self, alias) panel = cls.current_instance() if panel is not None: - _monkey_patch_cache(cache, alias) - cache._djdt_panel = panel + _monkey_patch_cache(cache, alias, panel) return cache CacheHandler.create_connection = wrapper @@ -194,10 +194,8 @@ def enable_instrumentation(self): # requests. The monkey patch of CacheHander.create_connection() installed in # the .ready() method will ensure that any new cache connections that get opened # during this request will also be monkey patched. - for alias in caches: - if hasattr(caches._connections, alias): - _monkey_patch_cache(caches[alias], alias) - caches[alias]._djdt_panel = self + for cache, alias in self.initialized_caches(): + _monkey_patch_cache(cache, alias, self) # Mark this panel instance as the current one for the active thread/async task # context. This will be used by the CacheHander.create_connection() monkey # patch. @@ -209,6 +207,17 @@ def disable_instrumentation(self): for cache in caches.all(initialized_only=True): cache._djdt_panel = None + def initialized_caches(self): + """ + Return the initialized caches and aliases. + + This does the same as`caches.all(initialized_only=True)`, but keeps + the alias with each cache instance. + """ + for alias in caches: + if hasattr(caches._connections, alias): + yield caches[alias], alias + def generate_stats(self, request, response): self.record_stats( {