django-sqllogging
Pretty, useful SQL logging for Django development.
- Re-formats and syntax-highlights SQL queries in the terminal
- Color-codes mutation queries (INSERT, UPDATE, DELETE, ALTER); syntax-highlights SELECTs
- Logs queries before execution with inlined parameters
- Logs query duration with slow-query highlighting
- Shows the request path that triggered each query
- Shows stack traces to find where queries originate
- Detects implicitly loaded relations (forward FK, forward/reverse one-to-one)
Installation
pip install django-sqllogging
Quick Start
Add django_sqllogging to your installed apps:
# settings.py
INSTALLED_APPS = [
# ...
"django_sqllogging",
]
Then control SQL logging via the sqldebug environment variable:
# Log all queries
sqldebug=query python manage.py runserver
# Log queries with stack traces
sqldebug=query,stack python manage.py runserver
# Log queries with the request path (requires middleware, see below)
sqldebug=query,request python manage.py runserver
# Log implicitly loaded relations
sqldebug=rels python manage.py runserver
# Everything
sqldebug=query,stack,rels,request python manage.py runserver
That's it — when sqldebug is set and no explicit logging configuration exists, a default handler is added automatically.
For custom logging setups (file output, different formatters, etc.), see Advanced Configuration.
Example Output
With sqldebug=query:
[django_sqllogging] ===>
SELECT id, name, email
FROM myapp_user
WHERE active = 1
AND role = 'admin'
ORDER BY created_at;
SQL Time: 0.0023
With sqldebug=rels:
[django_sqllogging] ===> 'profile' implicitly fetched on 'User'
Mutation queries (INSERT, UPDATE, DELETE) are color-coded. Slow queries (>0.1s by default) show the duration in red. In stack mode, a filtered stack trace appears above each query showing the application code that triggered it.
Shortcuts
| Value | Equivalent |
|---|---|
1 or t |
query |
2 |
query,stack |
trace |
stack |
0 or f |
disabled |
Request Path Tracking
To display the request path that triggered each query, add the middleware early in the list — queries from middleware above it won't have request context:
MIDDLEWARE = [
"django_sqllogging.middleware.sql_logging_middleware",
# ... other middleware
]
Then use sqldebug=query,request or sqldebug=query,stack (stack mode includes the request path automatically).
The middleware supports both WSGI and ASGI (sync and async Django).
Third-party compatibility
If you already have django-crum or django-threadlocals middleware active in your MIDDLEWARE, the built-in middleware is unnecessary — django-sqllogging auto-detects these libraries and reads the current request from them. No configuration needed.
Without any middleware (built-in or third-party), request path display silently shows nothing.
How It Works
When django_sqllogging is in INSTALLED_APPS and the logger is configured, the library patches Django's CursorDebugWrapper (used when DEBUG = True) to log queries before execution with inlined parameters. It also patches relation descriptors to detect implicit relation loading.
These patches are dormant when the sqldebug env var is not set — the overhead is negligible (one attribute check per query or relation access).
Request path tracking uses a lightweight ContextVar-based middleware (or auto-detects compatible third-party middleware) instead of walking the call stack.
Advanced Configuration
Using SqlFormatter with a different handler
SqlFormatter can be used independently with any handler (FileHandler, SysLogHandler, etc.):
LOGGING = {
"version": 1,
"disable_existing_loggers": False,
"formatters": {
"sql": {
"()": "django_sqllogging.SqlFormatter",
"project_name": "myapp",
},
},
"filters": {
"sql_debug": {"()": "django_sqllogging.SqlDebugFilter"},
},
"handlers": {
"sql_file": {
"class": "logging.FileHandler",
"filename": "sql.log",
"formatter": "sql",
"filters": ["sql_debug"],
},
},
"loggers": {
"django_sqllogging": {"level": "DEBUG", "handlers": ["sql_file"], "propagate": False},
},
}
SqlDebugFilter suppresses records when the sqldebug env var is not set. Without it, all SQL records are written regardless of sqldebug.
Overriding SQL_DEBUG programmatically
The sqldebug env var is auto-detected at startup. To override it in settings:
SQL_DEBUG = {"query", "stack"} # Always enable query + stack mode
If SQL_DEBUG is set explicitly in settings (even to None), the env var is ignored.
Formatter Options
| Option | Default | Description |
|---|---|---|
project_name |
Last component of BASE_DIR |
Controls how stack trace paths are shortened |
slow_threshold |
0.1 (seconds) |
Duration above this is highlighted red |
max_sql_length |
10000 (chars) |
SQL longer than this is truncated |
Requirements
- Python 3.12+
- Django 5.2+ with
DEBUG = True(pre-execution logging usesCursorDebugWrapper)
See also
- nplusone — N+1 query detection for Django and SQLAlchemy with middleware-based profiling, eager-load analysis, and test-mode exceptions. Unmaintained since 2020 but stable.
License
BSD 3-Clause. See LICENSE for details.
Metadata
Release files for django-sqllogging 1.0.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| django_sqllogging-1.0.1.tar.gz | 11.5 kB | With provenance | Details for django_sqllogging-1.0.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| django_sqllogging-1.0.1-py3-none-any.whl | Python 3 | none | any | Details for django_sqllogging-1.0.1-py3-none-any.whl |
Total release size: 24.9 kB
Release files / django_sqllogging-1.0.1.tar.gz
| Download URL | django_sqllogging-1.0.1.tar.gz |
|---|---|
| Size | 11.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c908b3c811cc860f9ca8e25bacd2fcc08a5a13e0812e483cd5b75cee68bdd32d
|
|
BLAKE2b-256 checksum How to use checksums |
58c6c8c3aa2b8d8112690762bc946058343219ecbf4f5906d7656c1daa60365d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 2, 2026.
Transparency logRelease files / django_sqllogging-1.0.1-py3-none-any.whl
| Download URL | django_sqllogging-1.0.1-py3-none-any.whl |
|---|---|
| Size | 13.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
1543ebf209025b7b46d27d02089be57f7799219b83fcf6cc4e5e1677a793887b
|
|
BLAKE2b-256 checksum How to use checksums |
78c36dbb34bf2bcf80d48c431e669262f793bb494f225dd9fa6397a83f918950
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.12
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 2, 2026.
Transparency logSecurity for django-sqllogging 1.0.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
All 2 files in this release have been uploaded with provenance metadata.
Attestation for django_sqllogging-1.0.1.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jun 2, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.