Skip to main content

django-query-doctor

Diagnose and fix slow Django ORM queries. Detects N+1s, duplicates, missing indexes, and more — with exact file:line references and actionable fixes.

PyPI Tests Python Django License

The Problem

Every Django app accumulates hidden query inefficiencies — N+1 loops behind serializers, duplicate fetches scattered across views, full table scans on unindexed columns. django-query-doctor intercepts queries at runtime using connection.execute_wrapper(), runs them through 8 analyzers, and produces prescriptions with the exact file, line, and code fix. It works in middleware, tests, CI pipelines, and management commands — no DEBUG=True required.

Install

pip install django-query-doctor
# settings.py
INSTALLED_APPS = [..., "query_doctor"]
MIDDLEWARE = [..., "query_doctor.middleware.QueryDoctorMiddleware"]

See It in Action

from query_doctor.context_managers import diagnose_queries

with diagnose_queries() as report:
    books = list(Book.objects.all())
    for book in books:
        _ = book.author.name  # triggers N+1

assert report.issues > 0
print(f"Found {report.issues} issues in {report.total_queries} queries")

Console output (plain-text renderer; Rich adds colors and panels):

============================================================
Query Doctor Report
Total queries: 13 | Time: 0.2ms | Issues: 2
============================================================

CRITICAL: N+1 detected: 12 queries for table "myapp_author" (field: author)
   Location: myapp/views.py:12 in list_books
   Code: _ = book.author.name  # triggers N+1
   Fix: Add .select_related('author') to your queryset
   Queries: 12 | Est. savings: ~0.2ms

INFO: Fat SELECT: 8 columns from "myapp_book" including large fields: description
   Location: myapp/views.py:10 in list_books
   Code: books = list(Book.objects.all())
   Fix: Use .defer('description') to skip loading large fields, or .values()/.values_list() if you don't need model instances
   Queries: 1 | Est. savings: ~0.0ms

What It Detects

Issue What It Catches
N+1 Queries Related objects loaded one-per-row in loops
Duplicate Queries Same SQL executed multiple times per request
Missing Indexes Filters on columns without database indexes
Fat SELECT Fetching all columns when only a few are used
QuerySet Evaluation len(qs) instead of qs.count(), bool(qs) instead of qs.exists()
Query Complexity Excessive JOINs, subqueries, or OR chains
SerializerMethodField AST analysis of get_<field> method bodies for hidden N+1s

Every prescription includes: severity, file:line, and the exact code fix.

QueryTurbo (v2.0)

QueryTurbo reduces SQL compilation overhead by caching compiled query structures and extracting parameters directly from Django's Query tree, bypassing repeated calls to SQLCompiler.as_sql(). Queries are validated across 3 executions before the compilation step is skipped entirely. Enable it in settings:

QUERY_DOCTOR = {
    "TURBO": {"ENABLED": True}
}

Full QueryTurbo guide →

Requirements

  • Python 3.10+
  • Django 4.2, 5.0, 5.1, 5.2, or 6.0
  • Optional extras: pip install django-query-doctor[rich] for styled console output, [celery] for Celery task support, [otel] for OpenTelemetry export
  • Optional third-party packages (install separately, not query-doctor extras): DRF for serializer analysis, psycopg3 for prepared-statement support

Links

📖 Documentation | 📦 PyPI | 📝 Changelog | 🐛 Issues

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

django_query_doctor-2.2.0.tar.gz (362.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

django_query_doctor-2.2.0-py3-none-any.whl (131.9 kB view details)

Uploaded Python 3

File details

Details for the file django_query_doctor-2.2.0.tar.gz.

File metadata

  • Download URL: django_query_doctor-2.2.0.tar.gz
  • Upload date:
  • Size: 362.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.12.0

File hashes

Hashes for django_query_doctor-2.2.0.tar.gz
Algorithm Hash digest
SHA256 9ea022beba34c5baa2155bf69d702acab0ae8127d42b52ee5d06a96c64966ef7
MD5 244b6404548c689f92c2db676e0d80a6
BLAKE2b-256 efec5fd21b69c09c08265550fc2a695e57d8c79be0e04c9bd87bc1632c533328

See more details on using hashes here.

File details

Details for the file django_query_doctor-2.2.0-py3-none-any.whl.

File metadata

File hashes

Hashes for django_query_doctor-2.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 8373dcd176ef53737a55ccac9fb04ff9db75c0d2e93203b582bd27817e4417a7
MD5 6c1f0c55cf8b75c899d467668985c2bf
BLAKE2b-256 aa065320e4ea2083dd0616fe9c20138a6b1616ec0bf0ca9c9ffc934fd3e0f714

See more details on using hashes here.

Release history Release notifications | RSS feed

2.3.0

2 files

This release

2.2.0 This release

2 files

2.1.2

2 files

2.1.1

2 files

2.1.0

2 files

2.0.0

2 files

1.0.2

2 files

1.0.1

2 files

1.0.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page