django-debug-toolbar

A configurable panel of SQL queries, request timing, cache calls, and template data injected into every page for debugging Django apps.

Tool
PyPI
v7.1.1
8,378stars
BSD 3-Clause License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
88/100Excellent
Development Activity100
Maintenance72
Community80
Maturity60
Momentum40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
87/100Excellent
Architecture88
Code Quality92
Innovation78
Learning Curve90

Django Debug Toolbar is a configurable set of panels that render debug information about the current request/response directly in the browser. Originally created by Rob Hudson in 2008 and now maintained by the Django Commons organization, it has become one of the most widely installed tools in the Django ecosystem, with a stable release history stretching back over 15 years and continued active development.

The toolbar works by inserting itself as Django middleware. When a request comes in and the configured show-toolbar check passes, it instantiates a DebugToolbar, activates instrumentation (much of it via monkey-patching) across a set of built-in panels, and renders the collected metrics into the outgoing HTML response. Panels cover SQL queries (with duplicate/similar query detection), request and response headers, template rendering, cache operations, signals, static files, background tasks, profiling, and version information, and third-party panels extend this further.

Beyond the panel system, the project supports async Django views, a pluggable storage layer for toolbar history (in-memory by default, with database or cache-backed alternatives for persisting state across restarts), and CSP-nonce-aware rendering for sites with a Content Security Policy. It is BSD-3-Clause licensed with no paid tier, license keys, or feature gating of any kind.

What You Get

  • A configurable panel system covering SQL (with duplicate-query detection), request/response headers, templates, cache, signals, static files, background tasks, profiling, and package versions
  • Async-compatible middleware that instruments both sync and async Django views, with select panels disabled by default under async where full compatibility is still in progress
  • A pluggable store layer (MemoryStore by default) that can be swapped for DatabaseStore or CacheStore so toolbar history survives process restarts
  • A history panel that lets you revisit metrics for any prior request served since the app started
  • Server-Timing header support so panel data is also visible in browser devtools, not just the injected UI
  • A debug_toolbar_urls() helper and CSP-nonce-aware rendering for straightforward setup on sites with a Content Security Policy

Common Use Cases

  • Diagnosing N+1 queries - developers use the SQL panel’s query list and duplicate/similar detection to spot redundant ORM calls during local development
  • Profiling view performance - the timer and profiling panels break down where time is spent in a request so slow views can be optimized before shipping
  • Inspecting template context - the templates panel shows which templates rendered, in what order, and with what context, useful when debugging inheritance or include chains
  • Verifying cache behavior - the cache panel surfaces get/set/delete calls against configured caches, helpful when tuning cache keys or TTLs
  • Auditing installed versions - the versions panel lists Django and package versions in use, useful when triaging environment-specific bugs

Under The Hood

Architecture The toolbar is organized into three layers that the project’s own docs describe explicitly: debug_toolbar.middleware.DebugToolbarMiddleware decides whether to instrument a request and owns most Django-integration logic; debug_toolbar.toolbar.DebugToolbar orchestrates the panel lifecycle for a given request without needing to know about the host project; and the panels themselves (in debug_toolbar/panels/) do the actual metric collection, some via monkey-patching (e.g. the templates panel patches template rendering when its module loads) and others, like the settings panel, by simply reading data already available. The middleware supports both sync and async call paths (__call__/__acall__), enabling/disabling instrumentation around toolbar.process_request, then post-processing the response to inject rendered HTML via a regex split on a configurable INSERT_BEFORE marker and to attach any panel-contributed headers.

Tech Stack The library targets Python 3.10+ and Django 5.2+, with sqlparse as its only other runtime dependency for formatting SQL in the SQL panel. Async support is built on asgiref (async_to_sync/sync_to_async/iscoroutinefunction/markcoroutinefunction). The store layer uses Django’s cache framework and a HistoryEntry model for optional database-backed persistence, with a custom JSON encoder/decoder pair handling binary and GeoDjango PostGIS payloads. Packaging uses Hatchling with the version sourced directly from debug_toolbar/__init__.py rather than pkg_resources. The toolbar’s own frontend assets are tested with Vitest (Node 24+, @vitest/browser-playwright), separate from the Python test suite.

Code Quality The project has an extensive Python test suite (30+ test modules under tests/, including per-panel tests for SQL, cache, templates, static files, tasks, and async-panel compatibility) enforced by a coverage gate — pyproject.toml sets fail_under = 94 for debug_toolbar. Linting runs through Ruff with an unusually broad rule set enabled (bugbear, comprehensions, McCabe complexity, flake8-django, flake8-boolean-trap, isort, pyupgrade, and more), plus pre-commit and tox for multi-environment testing. GitHub Actions workflows cover tests, coverage reporting, and a zizmor security lint on the workflows themselves. Async and multi-threading support is documented candidly as still evolving, with certain panels intentionally disabled under async until compatibility work lands.

What Makes It Unique Rather than exposing debug data through logs or a separate admin UI, the toolbar renders directly into the page under test using monkey-patch-based instrumentation, giving zero-setup visibility into SQL, templates, cache, and timing without code changes. Its swappable store abstraction is a deliberate design choice — teams that need toolbar history to survive runserver restarts, or to work across multiple worker processes, can move from the default in-memory store to a database- or cache-backed one without altering how panels collect data, a flexibility most competing profilers don’t offer as a first-class configuration option.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search