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

Metadata

Release files for django-query-doctor 2.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for django-query-doctor 2.3.0
File Size Uploaded
django_query_doctor-2.3.0.tar.gz 400.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for django-query-doctor 2.3.0
File Interpreter ABI Platform
django_query_doctor-2.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 539.5 kB

Release files / django_query_doctor-2.3.0.tar.gz

Download URL django_query_doctor-2.3.0.tar.gz
Size 400.4 kB
Tags Source
SHA-256 checksum
How to use checksums
a30ed539691f9543a38501a1a23b52219f70a120cba7a81268c6377f137b07c0
BLAKE2b-256 checksum
How to use checksums
7fc8d16059c42331c637e906d5a12549bd25f8bf00670530b8238976df4f0b34
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.0

Release files / django_query_doctor-2.3.0-py3-none-any.whl

Download URL django_query_doctor-2.3.0-py3-none-any.whl
Size 139.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
29a768c0121f6f28ad95c7f28b3b64030262a7346dc828dbb3b6ae021259da13
BLAKE2b-256 checksum
How to use checksums
3d14ead4d55af0edb5757306236fd35dd6b201fe2d2cc0d810a808ce24006462
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.0

Release history Release notifications | RSS feed

This release

2.3.0 This release

2 release files

2.2.0

2 release files

2.1.2

2 release files

2.1.1

2 release files

2.1.0

2 release files

2.0.0

2 release files

1.0.2

2 release files

1.0.1

2 release files

1.0.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page