Quick Start¶
Basic Usage¶
After installation, the middleware will automatically detect N+1 queries during request handling and log warnings.
Example N+1 Query¶
# This triggers a warning:
users = list(User.objects.all())
for user in users:
print(user.profile) # N+1! Each access triggers a separate query
Fix with select_related¶
# No warning:
users = list(User.objects.select_related("profile").all())
for user in users:
print(user.profile) # Already loaded
Raise Exceptions in Tests¶
Using the pytest Plugin¶
# Automatic detection with marker
@pytest.mark.nplus1
def test_my_view(client):
client.get("/my-view/") # Fails if N+1 detected
# Manual detection with fixture
def test_manual(nplus1):
users = list(User.objects.all())
users[0].profile # Raises NPlus1Error
Using the Profiler¶
from django_nplus1 import Profiler
with Profiler():
users = list(User.objects.all())
users[0].profile # Raises NPlus1Error
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.