Open-source project
django-commons/django-debug-toolbar avatar
django-commons/django-debug-toolbar

django-debug-toolbar: eighteen years of panels bolted onto Django's response

A configurable set of panels that display various debug information about the current request/response.

8,379 stars1,105 forksPythonBSD-3-Clause

At a glance

What is it?
The most installed debugging tool in the Django world, now at 8.0.0 with a redesigned toolbar, a Tasks panel, and a documented gap around concurrent requests.
Who is it for?
For a Django project under active development, the toolbar is close to mandatory, and version 8.0.0 published on 2026-09-01 is a good point to be on because it added the redesign and Django 6.1 support. It is a development tool, not a profiler for production, and it still cannot handle concurrent requests, which the README states outright.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 17 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 21, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the toolbar actually attaches itself to

The README describes the project in one sentence and it is accurate: a configurable set of panels that display debug information about the current request and response, showing more detail when clicked. The architecture follows from that. It is a Django middleware, and it intercepts the response on its way out, appending its own markup to the HTML body.

Because it works at the response layer rather than at the exception layer, a panel can report anything that happened during the request: how many SQL queries ran and what they were, how long each one took, what the template context looked like, what was in the cache, what the headers were. None of that requires Django to cooperate, which is why the toolbar can instrument views it knows nothing about, including third-party packages.

The rendering has moved on from what 8.0.0 shipped. The changelog for 8.0.0, published on 2026-09-01, records a refresh of the visual design with self-hosted Alef and Geist fonts, an updated colour palette, per-panel navigation icons, and a new logo. It also records that screenshot capture now looks inside the shadow DOM to find the toolbar elements, which is the detail that tells you how the current version is built: the toolbar lives in a shadow root, so it can carry its own styles without colliding with the host page.

That shadow root is also why the 7.1.0 changelog contains a fix for an error shown when panel content failed to load, which could not find the toolbar window inside the shadow root. An architectural choice that buys style isolation costs a layer of debugging when something inside it fails to appear.

Installing it in a project, and running the bundled example

The package installs from PyPI with pip, and the dependency list in `pyproject.toml` is short: `django>=5.2` and `sqlparse>=0.2`. That second dependency is worth understanding, because it exists so the SQL panel can pretty-print queries rather than showing raw parameter strings, which is a small quality of life difference that matters more than it sounds when you are reading a query list.

Python support starts at 3.10 and the classifiers run through 3.14. The project is built with hatchling, and `setup.py` is a deliberate stub that prints an error and exits non-zero, telling you to use `python -m pip install .` instead. That is a small thing worth noticing because it is a policy statement: the project has closed off the legacy install path on purpose.

The repository ships a complete example application under `example/`, including `manage.py`, `settings.py`, `urls.py`, `views.py`, `test_views.py`, an ASGI entry point and a SQLite database. The Makefile drives it:

bash
make example

That target migrates, creates a superuser with a throwaway email address and a fixed password of `p`, then runs the development server. There is an async variant, `make example_async`, which uses daphne against `example.asgi:application` rather than the WSGI server, and the async views live in `example/async_/`. The test suite has its own targets: `make test` runs Django's own test runner with `DJANGO_SETTINGS_MODULE=tests.settings`, and `make test_selenium` runs the frontend tests behind a `DJANGO_SELENIUM_TESTS=true` flag. There is also a `make coverage` target that writes terminal, HTML and XML reports.

The version floor that keeps breaking tutorials

The current stable version is 8.0.0 and it works on Django 5.2 and later. That floor is high compared with what most tutorials on the web still say, and it is the single most common reason an installation fails or a configuration snippet does nothing.

The version history in the tree shows the project keeping pace with Django's own cadence. 7.1.0, published on 2026-08-10, added support for Django 6.1. It also added the Tasks panel, which shows tasks queued during the request through Django's built-in tasks framework, and on older versions of Django the panel explains that an upgrade is required rather than hiding itself. Django 6.0 and 6.1 both appear in the framework classifiers. The Tasks panel is the newest thing in the list and it is a good example of what the toolbar is for. Background work queued during a request is otherwise invisible; the panel turns it into a list you can read next to the SQL panel. The follow-up release 7.1.1 on 2026-08-14 serialised the `TaskResult` class to accommodate the storage mechanism, which is the small amount of breakage that comes with tracking a framework API that is still settling. Async support is described as experimental and it comes with a caveat that deserves to be repeated: the toolbar still lacks the capability for handling concurrent requests. The release notes also record a fix for `show_toolbar_with_docker` on runtimes such as OrbStack that resolve `host.docker.internal` to an address outside the container network, so if you are running Django in Docker, that setting has a documented history of not doing what you expect.

Accessibility work in 8.0.0 that is more than a logo

It would be easy to read the 8.0.0 changelog as a cosmetic release and skip it. The accessibility paragraph is the one to read carefully: visible keyboard focus, keyboard-operable scroll regions, reduced-motion support, `aria-expanded` on panel toggles, an `aria-live` status for history refreshes, and WCAG 2.1 AA contrast in both themes. That is a real change in what the toolbar asks of the browser, and it has a practical consequence for anyone embedding it in a workflow. A developer who navigates by keyboard can now move through panels, which sounds minor until you are pairing on a slow query over a screen reader. The `aria-live` region for history refreshes matters too, because the history panel reloads without a page navigation and a screen reader user would otherwise get no signal that anything happened. The highlight colour change is the part most people will notice. The current request and other rows described as relevant to you moved from a yellow highlight to a green tint with a left border accent, chosen for legibility in dark mode. The highlight was the original way to find your own query in the SQL list, so changing its colour is not merely cosmetic: anyone who learned to scan for yellow has to relearn the cue. The release also added a Docs link that opens the documentation and a design guidelines page describing the logo, colour palette and typography. Self-hosted fonts are part of that. Shipping Alef and Geist with the toolbar rather than loading them from a font CDN keeps the debug page from making third-party requests on every page load, which matters for anyone running the toolbar in a network where outbound requests are logged.

Licence, provenance and what a package this old owes you

The toolbar is released under the BSD licence, like Django itself, and `pyproject.toml` records it as BSD-3-Clause. For a development-only dependency that is about as permissive as it gets: no copyleft obligation, no network clause, no branding restriction beyond the notice itself. The provenance is worth stating because the tool is older than most of the frameworks it now instruments. It was originally created by Rob Hudson in August 2008 and developed further by many contributors since. The current package is maintained under the django-commons organisation, and the pyproject authors field still lists Rob Hudson as the author of record. The repository is not archived and the last push was on 2026-09-20, so the release cadence is current: 7.1.0 in August, 7.1.1 two days later, 8.0.0 in September. The coverage badge in the README claims 94 percent, which for a tool whose whole job is instrumenting other people's code is a reasonable number and also a number worth reading as a claim rather than a guarantee, since the interesting cases are always the third-party panels. There is a JavaScript side to the project that surprises people who assume it is pure Python. `package.json` requires Node 24 and npm 11, with `vitest` as the test runner and `@vitest/browser-playwright` for browser-based tests. `biome.json` handles formatting and linting, and `.tx/` points at Transifex for translations, driven by the `make translatable_strings` and `make update_translations` targets. The panel frontend is modern tooling in a project most people still think of as a 2010s Django package.

Where the toolbar is the wrong tool

The first wrong-tool case is production. The toolbar renders HTML into every response, keeps per-request state in the browser and in the Django process, and is built for a single developer looking at one request at a time. Running it on a production site to watch traffic is not a supported use and the panel list will not tell you what your users actually experience. The second is concurrency, which the README names: concurrent requests are not handled. Any server that interleaves requests, which includes anything with async views, can mix panel state between requests. The async support is marked experimental for the same reason. If you need to reason about a specific response, capture it. If you need to reason about aggregate behaviour, you want a different tool. The third is profiling at scale. The SQL panel tells you which queries ran and how long each took on one request, which is exactly what you want when a page is slow. It is not a sampling profiler and it does not attribute CPU time across a whole application, so the moment the question becomes where the process spends its time overall, the toolbar has nothing to offer. There is a fourth, narrower trap. Because panels work by inspecting the response, a panel that fails to load produces an error rather than an absence, and 7.1.0 had to fix exactly that case in the shadow root. On a project with a third-party panel that misbehaves, the useful move is to disable that panel rather than debug the toolbar, and the related search terms show this is where people actually land: the top related queries are about the toolbar not showing at all, how to install it, and Django's `DEBUG = True`.

Editorial conclusion

For a Django project under active development, the toolbar is close to mandatory, and version 8.0.0 published on 2026-09-01 is a good point to be on because it added the redesign and Django 6.1 support. It is a development tool, not a profiler for production, and it still cannot handle concurrent requests, which the README states outright. Install it, then read `docs/installation.rst` for the middleware ordering and the `INTERNAL_IPS` setting, because the panel not appearing is almost always a configuration mistake rather than a bug. Reach for a sampling profiler such as py-spy when the question is where wall clock time goes across many requests.

Frequently asked questions

How do I use the Django Debug Toolbar?

Install it with pip, add `debug_toolbar` to `INSTALLED_APPS`, add its middleware, and point `INTERNAL_IPS` at the addresses allowed to see it. Version 8.0.0 requires Django 5.2 or later and Python 3.10 or later. The sidebar renders into every response and each panel expands on click.

Why is the toolbar not showing on my page?

The usual causes are ordering and address filtering rather than a bug. The middleware has to run so its markup lands in the response, the templates have to render normally so the panel window can attach, and `INTERNAL_IPS` has to include the address the browser actually presents. The `make example` target in the repository builds a working project to compare against.

Does the toolbar work with Django REST Framework and async views?

Async views are supported experimentally, and the README is explicit that the toolbar still cannot handle concurrent requests, so mixed async traffic can mix panel state. For REST work it renders into the browsable API pages, and panels such as the Tasks panel show what was queued during the request on Django 6.0 and later.

Official sources

  1. django-commons/django-debug-toolbar on GitHub
  2. License: BSD-3-Clause
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/django-commons-django-debug-toolbar.svg)](https://hysenlabs.com/projects/django-commons-django-debug-toolbar)