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 7 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.1.2.tar.gz (309.8 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.1.2-py3-none-any.whl (119.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for django_query_doctor-2.1.2.tar.gz
Algorithm Hash digest
SHA256 226db985de293f595c1be4da8b1008d718a061bfe5a0f4f26df9ae0fa8624713
MD5 4b0f99e337cd20ec3be222fc3e42e8c6
BLAKE2b-256 36fe51251cbba2a96a6e5c4823d491e4dda58923cdfd1f68b042d87547110100

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for django_query_doctor-2.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 e005e69f4a36e82e9943ab45d2b6293350164916e0b763d3279b9bf08f384413
MD5 4a9c6ad9e7bdb79ba15e21700957b3b7
BLAKE2b-256 6dbcebdef0d7317b6e0a1a321920474c2ec38a87c0444ac742e094e5317586e5

See more details on using hashes here.

Release history Release notifications | RSS feed

2.3.0

2 files

2.2.0

2 files

This release

2.1.2 This release

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