Metadata-Version: 2.4
Name: django-query-doctor
Version: 2.0.0
Summary: Automated Django ORM query diagnosis and optimization. SQL compilation caching, prepared statements, N+1 detection, and DRF analysis.
Project-URL: Homepage, https://github.com/hassanzaibhay/django-query-doctor
Project-URL: Documentation, https://hassanzaibhay.github.io/django-query-doctor
Project-URL: Repository, https://github.com/hassanzaibhay/django-query-doctor
Project-URL: Changelog, https://github.com/hassanzaibhay/django-query-doctor/blob/main/CHANGELOG.md
Project-URL: Bug Tracker, https://github.com/hassanzaibhay/django-query-doctor/issues
Author-email: Hassan Zaib Hayat <hassanzaibhayatske@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: cache,diagnosis,django,drf,n+1,optimization,orm,performance,prepared-statements,profiling,query,rest-framework,sql
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: Django
Classifier: Framework :: Django :: 4.2
Classifier: Framework :: Django :: 5.0
Classifier: Framework :: Django :: 5.1
Classifier: Framework :: Django :: 5.2
Classifier: Framework :: Django :: 6.0
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Database
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: Software Development :: Quality Assurance
Requires-Python: >=3.10
Requires-Dist: django>=4.2
Provides-Extra: all
Requires-Dist: celery>=5.0; extra == 'all'
Requires-Dist: opentelemetry-api>=1.0; extra == 'all'
Requires-Dist: opentelemetry-sdk>=1.0; extra == 'all'
Requires-Dist: rich>=13.0; extra == 'all'
Provides-Extra: celery
Requires-Dist: celery>=5.0; extra == 'celery'
Provides-Extra: dev
Requires-Dist: asgiref>=3.7; extra == 'dev'
Requires-Dist: django-stubs>=4.2; extra == 'dev'
Requires-Dist: djangorestframework>=3.14; extra == 'dev'
Requires-Dist: factory-boy>=3.3; extra == 'dev'
Requires-Dist: mypy>=1.8; extra == 'dev'
Requires-Dist: pytest-cov>=4.0; extra == 'dev'
Requires-Dist: pytest-django>=4.7; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.4; extra == 'dev'
Provides-Extra: docs
Requires-Dist: mkdocs-git-revision-date-localized-plugin>=1.2; extra == 'docs'
Requires-Dist: mkdocs-material>=9.5; extra == 'docs'
Requires-Dist: mkdocstrings[python]>=0.24; extra == 'docs'
Provides-Extra: otel
Requires-Dist: opentelemetry-api>=1.0; extra == 'otel'
Requires-Dist: opentelemetry-sdk>=1.0; extra == 'otel'
Provides-Extra: rich
Requires-Dist: rich>=13.0; extra == 'rich'
Description-Content-Type: text/markdown

# 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](https://img.shields.io/pypi/v/django-query-doctor.svg)](https://pypi.org/project/django-query-doctor/)
[![Tests](https://img.shields.io/github/actions/workflow/status/hassanzaibhay/django-query-doctor/ci.yml)](https://github.com/hassanzaibhay/django-query-doctor/actions)
[![Python](https://img.shields.io/pypi/pyversions/django-query-doctor.svg)](https://pypi.org/project/django-query-doctor/)
[![Django](https://img.shields.io/badge/django-4.2%20|%205.0%20|%205.1%20|%205.2%20|%206.0-blue)](https://pypi.org/project/django-query-doctor/)
[![License](https://img.shields.io/pypi/l/django-query-doctor.svg)](https://opensource.org/licenses/MIT)

## 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

```bash
pip install django-query-doctor
```

```python
# settings.py
INSTALLED_APPS = [..., "query_doctor"]
MIDDLEWARE = [..., "query_doctor.middleware.QueryDoctorMiddleware"]
```

## See It in Action

```python
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")
```

Output:

```
[CRITICAL] N+1 Query
  50 queries fetching Author for each Book.
  Location: views.py:42
  Fix: Add select_related('author') to queryset
```

## 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()` |
| DRF Serializer | N+1 from nested serializers or missing `select_related` |
| 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:

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

[Full QueryTurbo guide →](https://hassanzaibhay.github.io/django-query-doctor/guides/queryturbo/)

## Requirements

- Python 3.10+
- Django 4.2, 5.0, 5.1, 5.2, or 6.0
- Optional: Rich (styled console), DRF (serializer analysis), psycopg3 (prepared statements)

## Links

[📖 Documentation](https://hassanzaibhay.github.io/django-query-doctor/)  |  [📦 PyPI](https://pypi.org/project/django-query-doctor/)  |  [📝 Changelog](https://hassanzaibhay.github.io/django-query-doctor/changelog/)  |  [🐛 Issues](https://github.com/hassanzaibhay/django-query-doctor/issues)

## License

MIT
