Quick Start¶
Recommended Setup¶
After installation, add the middleware to your test settings:
Now any view test that uses the Django test client will fail if an N+1 query is detected:
def test_list_authors(client, authors):
response = client.get("/authors/") # raises NPlus1Error if view has N+1
Why test settings?¶
Testing actual request paths catches real problems in your views. Helper functions or management commands that intentionally defer prefetching to their callers can produce false positives when wrapped in a detection context — testing through the middleware avoids that.
Adopting in an Existing Project¶
Introducing django-nplus1 to a project with existing N+1 queries will likely fail many tests at once. Whitelist the known issues and fix them over time:
# settings/testing.py
NPLUS1_WHITELIST = [
{"model": "myapp.Author", "field": "books"},
{"model": "myapp.Book", "field": "publisher"},
]
See Whitelisting for the full format including wildcards and nplus1_allow().
What Gets Detected¶
N+1 Queries¶
# This triggers detection:
users = list(User.objects.all())
for user in users:
print(user.profile) # N+1! Each access triggers a separate query
# Fix with select_related:
users = list(User.objects.select_related("profile").all())
for user in users:
print(user.profile) # Already loaded
Other Detections¶
- Deferred field access:
.defer()/.only()fields accessed in a loop .get()in a loop:Model.objects.get()called repeatedly from the same call-site- Unused eager loads:
select_related/prefetch_relatedresults that are never accessed
Other Options¶
The middleware in test settings is the recommended starting point, but django-nplus1 offers other ways to run detection:
Middleware in All Environments¶
Add the middleware to your base settings to log warnings during development or production:
pytest Plugin¶
For per-test control without the middleware:
See pytest Plugin for details.
Profiler¶
For manual use in scripts or tests:
from django_nplus1 import Profiler
with Profiler():
users = list(User.objects.all())
users[0].profile # Raises NPlus1Error
Celery Tasks¶
The equivalent of the middleware for Celery tasks:
Each task gets its own detection context, so N+1 queries inside task.delay() or task.apply() are reported the same way as in HTTP requests.