Skip to content

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
# No warning:
users = list(User.objects.select_related("profile").all())
for user in users:
    print(user.profile)  # Already loaded

Raise Exceptions in Tests

# settings/test.py
NPLUS1_RAISE = True  # Raise NPlus1Error instead of logging

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

# settings.py
NPLUS1_CELERY = True

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.