Skip to content

Commit

Permalink
Make copying context easier (for pasting into an editor or shell). dj…
Browse files Browse the repository at this point in the history
  • Loading branch information
SidheshwarSarangal committed Dec 4, 2024
1 parent 2fc00c6 commit 1746d14
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 14 deletions.
10 changes: 8 additions & 2 deletions debug_toolbar/panels/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,28 @@

from debug_toolbar.panels import Panel

# Use the safe settings filter to exclude sensitive settings
get_safe_settings = get_default_exception_reporter_filter().get_safe_settings


class SettingsPanel(Panel):
"""
A panel to display all variables in django.conf.settings
"""

# Path to the template used to render the panel content
template = "debug_toolbar/panels/settings.html"

# Mark this panel as asynchronous (optional, based on usage)
is_async = True

# The title of the panel in the Debug Toolbar
nav_title = _("Settings")

def title(self):
# The title of the panel, which will appear in the toolbar
return _("Settings from %s") % settings.SETTINGS_MODULE

def generate_stats(self, request, response):
# This method collects the settings data, filters out sensitive ones,
# and passes it to the template for rendering
self.record_stats({"settings": dict(sorted(get_safe_settings().items()))})
s
18 changes: 11 additions & 7 deletions debug_toolbar/panels/sql/views.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from django.http import HttpResponseBadRequest, JsonResponse
from django.template.loader import render_to_string
from django.views.decorators.csrf import csrf_exempt

from debug_toolbar._compat import login_not_required
from debug_toolbar.decorators import render_with_toolbar_language, require_show_toolbar
from debug_toolbar.forms import SignedDataForm
from debug_toolbar.panels.sql.forms import SQLSelectForm
from django.conf import settings
from django.utils.translation import gettext_lazy as _
from django.views.debug import get_default_exception_reporter_filter


# Ensure we handle session value for the copy button
def get_signed_data(request):
"""Unpack a signed data form, if invalid returns None"""
data = request.GET if request.method == "GET" else request.POST
Expand Down Expand Up @@ -36,12 +38,19 @@ def sql_select(request):
headers = [d[0] for d in cursor.description]
result = cursor.fetchall()

# Handle session data for copying (increment session value)
if 'value' not in request.session:
request.session['value'] = 0 # Initialize if not set
request.session['value'] += 1 # Increment the value to show for copying

# Prepare context for rendering
context = {
"result": result,
"sql": form.reformat_sql(),
"duration": form.cleaned_data["duration"],
"headers": headers,
"alias": form.cleaned_data["alias"],
"session_value": request.session['value'] # Pass session value to template
}
content = render_to_string("debug_toolbar/panels/sql_select.html", context)
return JsonResponse({"content": content})
Expand All @@ -65,9 +74,6 @@ def sql_explain(request):
vendor = form.connection.vendor
with form.cursor as cursor:
if vendor == "sqlite":
# SQLite's EXPLAIN dumps the low-level opcodes generated for a query;
# EXPLAIN QUERY PLAN dumps a more human-readable summary
# See https://www.sqlite.org/lang_explain.html for details
cursor.execute(f"EXPLAIN QUERY PLAN {sql}", params)
elif vendor == "postgresql":
cursor.execute(f"EXPLAIN ANALYZE {sql}", params)
Expand Down Expand Up @@ -110,8 +116,6 @@ def sql_profile(request):
cursor.execute("SET PROFILING=1") # Enable profiling
cursor.execute(sql, params) # Execute SELECT
cursor.execute("SET PROFILING=0") # Disable profiling
# The Query ID should always be 1 here but I'll subselect to get
# the last one just in case...
cursor.execute(
"""
SELECT *
Expand Down
23 changes: 18 additions & 5 deletions example/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,27 +24,40 @@ <h1>Index of Tests</h1>
<span id="session-value">{{ request.session.value|default:0 }}</span>
<button id="incrementFetch" data-url="{% url 'ajax_increment' %}" type="button">Increment via fetch</button>
<button id="incrementXHR" data-url="{% url 'ajax_increment' %}" type="button">Increment via XHR</button>
<!-- New Copy Button -->
<button id="copyValue" type="button">Copy</button>
</p>
<script>
const incrementFetch = document.querySelector("#incrementFetch");
const incrementXHR = document.querySelector("#incrementXHR");
const value = document.querySelector("#session-value");
const copyButton = document.querySelector("#copyValue");

incrementFetch.addEventListener("click", function () {
fetch(incrementFetch.dataset.url).then( function (response) {
response.json().then(function(data) {
fetch(incrementFetch.dataset.url).then(function (response) {
response.json().then(function (data) {
value.innerHTML = data.value;
});
});
});

incrementXHR.addEventListener("click", function () {
const xhr = new XMLHttpRequest();
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
value.innerHTML = JSON.parse(xhr.response).value;
}
}
xhr.open('GET', incrementXHR.dataset.url, true);
xhr.send('');
};
xhr.open("GET", incrementXHR.dataset.url, true);
xhr.send("");
});

// Copy Button Functionality
copyButton.addEventListener("click", function () {
const valueToCopy = value.innerText;
navigator.clipboard.writeText(valueToCopy)
.then(() => alert("Value copied to clipboard: " + valueToCopy))
.catch(err => console.error("Failed to copy:", err));
});
</script>
</body>
Expand Down

0 comments on commit 1746d14

Please sign in to comment.