diff --git a/debug_toolbar/panels/history/panel.py b/debug_toolbar/panels/history/panel.py index 8bd0e8f65..3a55c9d51 100644 --- a/debug_toolbar/panels/history/panel.py +++ b/debug_toolbar/panels/history/panel.py @@ -87,7 +87,9 @@ def content(self): Fetch every store for the toolbar and include it in the template. """ stores = {} - for id, toolbar in reversed(self.toolbar._store.items()): + + list_obj = self.toolbar.fetch_all(self.toolbar) + for id, toolbar in reversed(list_obj.items()): stores[id] = { "toolbar": toolbar, "form": HistoryStoreForm( diff --git a/debug_toolbar/panels/history/views.py b/debug_toolbar/panels/history/views.py index 3fcbd9b32..165e13d9f 100644 --- a/debug_toolbar/panels/history/views.py +++ b/debug_toolbar/panels/history/views.py @@ -14,7 +14,8 @@ def history_sidebar(request): if form.is_valid(): store_id = form.cleaned_data["store_id"] - toolbar = DebugToolbar.fetch(store_id) + tb = DebugToolbar(request, request) + toolbar = DebugToolbar.fetch(tb, store_id) exclude_history = form.cleaned_data["exclude_history"] context = {} if toolbar is None: @@ -46,7 +47,9 @@ def history_refresh(request): if form.is_valid(): requests = [] # Convert to list to handle mutations happening in parallel - for id, toolbar in list(DebugToolbar._store.items()): + tb = DebugToolbar(request, request) + list_obj = DebugToolbar.fetch_all(tb) + for id, toolbar in list(list_obj.items()): requests.append( { "id": id, diff --git a/debug_toolbar/settings.py b/debug_toolbar/settings.py index bf534a7da..d7cfed2a6 100644 --- a/debug_toolbar/settings.py +++ b/debug_toolbar/settings.py @@ -42,6 +42,7 @@ "SQL_WARNING_THRESHOLD": 500, # milliseconds "OBSERVE_REQUEST_CALLBACK": "debug_toolbar.toolbar.observe_request", "TOOLBAR_LANGUAGE": None, + "CACHE_TIME": 100, } diff --git a/debug_toolbar/toolbar.py b/debug_toolbar/toolbar.py index 40e758107..ceaa8a8be 100644 --- a/debug_toolbar/toolbar.py +++ b/debug_toolbar/toolbar.py @@ -43,6 +43,7 @@ def __init__(self, request, get_response): self.stats = {} self.server_timing_stats = {} self.store_id = None + self.cache_key = "djangodebug_" self._created.send(request, toolbar=self) # Manage panels @@ -75,6 +76,8 @@ def render_toolbar(self): """ if not self.should_render_panels(): self.store() + if self.tests_run(): + return "" try: context = {"toolbar": self} lang = self.config["TOOLBAR_LANGUAGE"] or get_language() @@ -90,6 +93,9 @@ def render_toolbar(self): else: raise + def tests_run(self): + return self.config.get("TESTS_RUN", False) + def should_render_panels(self): """Determine whether the panels should be rendered during the request @@ -109,13 +115,55 @@ def store(self): if self.store_id: return self.store_id = uuid.uuid4().hex - self._store[self.store_id] = self - for _ in range(self.config["RESULTS_CACHE_SIZE"], len(self._store)): - self._store.popitem(last=False) + + from django.core.cache import cache + + data = { + "stats": self.stats, + "server_timing_stats": self.server_timing_stats, + } + + cache.set(f"{self.cache_key}{self.store_id}", data, self.config["CACHE_TIME"]) + + @classmethod + def fetch(cls, tb, store_id): + from django.core.cache import cache + + data = cache.get(f"{tb.cache_key}{store_id}") + if data: + tb.stats = data.get("stats", {}) + tb.server_timing_stats = data.get("server_timing_stats", {}) + + sql_plugin_data = tb.stats.get("SQLPanel") + if sql_plugin_data: + databases_data = sql_plugin_data.get("databases", [("default", {})])[0][ + 1 + ] + tb._panels.get("SQLPanel")._num_queries = databases_data.get( + "num_queries" + ) + tb._panels.get("SQLPanel")._sql_time = sql_plugin_data.get("sql_time") + tb.store_id = store_id + return tb @classmethod - def fetch(cls, store_id): - return cls._store.get(store_id) + def fetch_all(cls, tb): + import copy + + from django.core.cache import cache + + data_dict = {} + key_list = cache.keys(f"{tb.cache_key}*") + for key in key_list: + store_id = key.split("_")[1] + data = cache.get(key) + new_tb = copy.copy(tb) + new_tb.stats = data["stats"] + new_tb.server_timing_stats = data["server_timing_stats"] + new_tb.store_id = store_id + data_dict[store_id] = new_tb + + return data_dict # Manually implement class-level caching of panel classes and url patterns # because it's more obvious than going through an abstraction. diff --git a/debug_toolbar/views.py b/debug_toolbar/views.py index b93acbeed..448ffb491 100644 --- a/debug_toolbar/views.py +++ b/debug_toolbar/views.py @@ -10,7 +10,8 @@ @render_with_toolbar_language def render_panel(request): """Render the contents of a panel""" - toolbar = DebugToolbar.fetch(request.GET["store_id"]) + tb = DebugToolbar(request, request) + toolbar = DebugToolbar.fetch(tb, request.GET["store_id"]) if toolbar is None: content = _( "Data for this panel isn't available anymore. "