### Install nplusone from PyPI Source: https://github.com/jmcarp/nplusone/blob/master/docs/install.md Use pip to install the latest version of nplusone. This is the recommended installation method. ```bash pip install -U nplusone ``` -------------------------------- ### Install nplusone from Source Source: https://github.com/jmcarp/nplusone/blob/master/docs/install.md After cloning the repository, use the setup.py script to install nplusone locally. ```bash python setup.py install ``` -------------------------------- ### Django Integration: Settings and Example View Source: https://context7.com/jmcarp/nplusone/llms.txt Configure Django settings for nplusone by adding the extension to INSTALLED_APPS and the middleware to MIDDLEWARE. Set NPLUSONE_LOGGER, NPLUSONE_LOG_LEVEL, NPLUSONE_RAISE, and NPLUSONE_WHITELIST as needed. The example view shows a common n+1 query pattern and its optimized solution using prefetch_related. ```python # settings.py import logging INSTALLED_APPS = [ # ... other apps ... 'nplusone.ext.django', ] MIDDLEWARE = [ 'nplusone.ext.django.NPlusOneMiddleware', # ... other middleware ... ] # Log warnings to a named logger NPLUSONE_LOGGER = logging.getLogger('nplusone') NPLUSONE_LOG_LEVEL = logging.WARN # Raise an exception instead of (or in addition to) logging NPLUSONE_RAISE = True # causes NPlusOneError on any detected n+1 # Whitelist specific models or fields to suppress known false positives NPLUSONE_WHITELIST = [ {'label': 'n_plus_one', 'model': 'myapp.User'}, # exact app.Model {'model': 'myapp.*'}, # fnmatch wildcard {'label': 'unused_eager_load', 'model': 'myapp.Order', 'field': 'items'}, ] LOGGING = { 'version': 1, 'handlers': { 'console': {'class': 'logging.StreamHandler'}, }, 'loggers': { 'nplusone': { 'handlers': ['console'], 'level': 'WARN', 'propagate': False, }, }, } # --- Example view that triggers a warning --- # views.py from django.http import JsonResponse from myapp.models import User def user_list(request): # BAD: lazy-loads `addresses` for every user → n+1 queries users = User.objects.all() data = [{'id': u.id, 'addresses': list(u.addresses.values())} for u in users] return JsonResponse({'users': data}) # → nplusone logs: "Potential n+1 query detected on `User.addresses`" def user_list_fixed(request): # GOOD: prefetch_related eliminates the n+1 users = User.objects.prefetch_related('addresses').all() data = [{'id': u.id, 'addresses': list(u.addresses.values())} for u in users] return JsonResponse({'users': data}) # → no warning ``` -------------------------------- ### Flask-SQLAlchemy Integration: Setup and Configuration Source: https://context7.com/jmcarp/nplusone/llms.txt Integrate nplusone with Flask-SQLAlchemy by wrapping the Flask app instance with `NPlusOne`. Configure settings via `app.config`, including `NPLUSONE_LOGGER`, `NPLUSONE_LOG_LEVEL`, `NPLUSONE_RAISE`, and `NPLUSONE_WHITELIST`. This setup enables per-request listeners on SQLAlchemy relationship accessors. ```python import logging from flask import Flask, jsonify from flask_sqlalchemy import SQLAlchemy from nplusone.ext.flask_sqlalchemy import NPlusOne db = SQLAlchemy() nplusone = NPlusOne() def create_app(): app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://localhost/mydb' app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # nplusone configuration app.config['NPLUSONE_LOGGER'] = logging.getLogger('nplusone') app.config['NPLUSONE_LOG_LEVEL'] = logging.ERROR app.config['NPLUSONE_RAISE'] = True # raise NPlusOneError in tests app.config['NPLUSONE_WHITELIST'] = [ {'model': 'User', 'field': 'legacy_field'}, # suppress a known case ] db.init_app(app) nplusone.init_app(app) # or: NPlusOne(app) for the direct pattern return app # --- Models --- class User(db.Model): id = db.Column(db.Integer, primary_key=True) hobbies = db.relationship('Hobby', secondary='user_hobby', lazy='select') class Hobby(db.Model): id = db.Column(db.Integer, primary_key=True) name = db.Column(db.String(64)) ``` -------------------------------- ### Django Configuration Source: https://github.com/jmcarp/nplusone/blob/master/README.rst Add 'nplusone.ext.django' to INSTALLED_APPS and NPlusOneMiddleware to MIDDLEWARE. Optionally configure logging settings. ```python INSTALLED_APPS = ( ... 'nplusone.ext.django', ) ``` ```python MIDDLEWARE = ( 'nplusone.ext.django.NPlusOneMiddleware', ... ) ``` ```python NPLUSONE_LOGGER = logging.getLogger('nplusone') NPLUSONE_LOG_LEVEL = logging.WARN ``` ```python LOGGING = { 'version': 1, 'handlers': { 'console': { 'class': 'logging.StreamHandler', }, }, 'loggers': { 'nplusone': { 'handlers': ['console'], 'level': 'WARN', }, }, } ``` -------------------------------- ### Integrate NPlusOne with WSGI Applications Source: https://context7.com/jmcarp/nplusone/llms.txt Wrap your WSGI application with `NPlusOneMiddleware` to enable NPlusOne detection for frameworks not explicitly supported. Ensure the ORM extension is imported to activate instrumentation. ```python import bottle from nplusone.ext.wsgi import NPlusOneMiddleware import nplusone.ext.sqlalchemy # activate SQLAlchemy instrumentation app = bottle.Bottle() @app.route('/items') def items(): from myapp.models import session, Item return {'items': [i.name for i in session.query(Item).all()]} # Wrap the WSGI app; whitelist is optional application = NPlusOneMiddleware( app, whitelist=[ {'label': 'n_plus_one', 'model': 'Item', 'field': 'tags'}, ], ) # For Peewee instead of SQLAlchemy: # import nplusone.ext.peewee ``` -------------------------------- ### Configure nplusone Whitelist Rules (Flask-SQLAlchemy) Source: https://context7.com/jmcarp/nplusone/llms.txt Configure whitelist rules for Flask-SQLAlchemy applications using plain class names and supporting fnmatch wildcards. ```python # Flask-SQLAlchemy app.config (plain class names, no app_label prefix) app.config['NPLUSONE_WHITELIST'] = [ {'model': 'User'}, {'model': 'U*r'}, # fnmatch wildcard on class name {'label': 'unused_eager_load', 'model': 'Product', 'field': 'reviews'}, ] ``` -------------------------------- ### Configure nplusone Profiler Whitelist Source: https://context7.com/jmcarp/nplusone/llms.txt Use the Profiler context manager with a whitelist to suppress specific ORM query warnings in non-HTTP request contexts. ```python # Profiler whitelist (same dict format, passed as a list) from nplusone.core import profiler with profiler.Profiler(whitelist=[ {'label': 'n_plus_one', 'model': 'User'}, {'model': 'Legacy*'}, ]): run_batch_job() ``` -------------------------------- ### WSGI Application Wrapping Source: https://github.com/jmcarp/nplusone/blob/master/README.rst Wrap any WSGI-compliant application with NPlusOneMiddleware and import the relevant ORM extension. ```python import bottle from nplusone.ext.wsgi import NPlusOneMiddleware import nplusone.ext.sqlalchemy app = NPlusOneMiddleware(bottle.app()) ``` -------------------------------- ### Framework-Agnostic Profiling with NPlusOne.Profiler Source: https://context7.com/jmcarp/nplusone/llms.txt Use the `nplusone.core.profiler.Profiler` context manager for low-level API usage, suitable for tests or management commands outside HTTP request contexts. It activates all listeners and raises `NPlusOneError` on the first detected issue. ```python from nplusone.core import profiler import nplusone.ext.sqlalchemy # or nplusone.ext.peewee / nplusone.ext.django # Basic usage — raises NPlusOneError on detection with profiler.Profiler(): users = session.query(User).all() for user in users: _ = user.addresses # ← NPlusOneError raised here if lazy-loaded # With whitelist — suppress known acceptable patterns with profiler.Profiler(whitelist=[ {'label': 'n_plus_one', 'model': 'User', 'field': 'addresses'}, ]): users = session.query(User).all() for user in users: _ = user.addresses # suppressed — no error # Typical pytest usage import pytest from nplusone.core.exceptions import NPlusOneError def test_no_n_plus_one(db_session): with pytest.raises(NPlusOneError, match='User.addresses'): with profiler.Profiler(): users = db_session.query(User).all() for u in users: _ = u.addresses # confirms the n+1 exists before fixing it ``` -------------------------------- ### Configure nplusone Whitelist Rules (Django) Source: https://context7.com/jmcarp/nplusone/llms.txt Define whitelist rules in Django settings to suppress specific n+1 warnings. Rules can target models, fields, or use wildcards. ```python # Django settings.py — various whitelist patterns NPLUSONE_WHITELIST = [ # Suppress all n+1 warnings for a specific model {'label': 'n_plus_one', 'model': 'myapp.User'}, # Suppress unused eager load on a specific field {'label': 'unused_eager_load', 'model': 'myapp.Order', 'field': 'line_items'}, # Wildcard: suppress all warnings for any model in 'myapp' {'model': 'myapp.*'}, # Wildcard: match models starting with 'Legacy' {'model': 'myapp.Legacy*'}, ] ``` -------------------------------- ### Flask-SQLAlchemy Integration Source: https://github.com/jmcarp/nplusone/blob/master/README.rst Wrap your Flask application with NPlusOne. Optionally configure logging settings via app.config. ```python from flask import Flask from nplusone.ext.flask_sqlalchemy import NPlusOne app = Flask(__name__) NPlusOne(app) ``` ```python app = Flask(__name__) app.config['NPLUSONE_LOGGER'] = logging.getLogger('app.nplusone') app.config['NPLUSONE_LOG_LEVEL'] = logging.ERROR NPlusOne(app) ``` -------------------------------- ### Clone nplusone repository from GitHub Source: https://github.com/jmcarp/nplusone/blob/master/docs/install.md Clone the nplusone source code repository from GitHub to contribute or build from source. ```bash git clone https://github.com/jmcarp/nplusone.git ``` -------------------------------- ### Generic Profiler Usage Source: https://github.com/jmcarp/nplusone/blob/master/README.rst Use the Profiler context manager for nplusone outside of an HTTP request context. Ensure the relevant ORM extension is imported. ```python from nplusone.core import profiler import nplusone.ext.sqlalchemy with profiler.Profiler(): ... ``` -------------------------------- ### Configure Nplusone Whitelist (Django) Source: https://github.com/jmcarp/nplusone/blob/master/README.rst Define a whitelist in Django settings to ignore specific nplusone notifications. You can specify the label and model to ignore. ```python # Django config NPLUSONE_WHITELIST = [ {'label': 'n_plus_one', 'model': 'myapp.MyModel'} ] ``` -------------------------------- ### Configure Nplusone Whitelist (Flask-SQLAlchemy) Source: https://github.com/jmcarp/nplusone/blob/master/README.rst Configure a whitelist in Flask-SQLAlchemy settings to ignore specific nplusone notifications. You can specify the label, model, and field to ignore. ```python # Flask-SQLAlchemy config app.config['NPLUSONE_WHITELIST'] = [ {'label': 'unused_eager_load', 'model': 'MyModel', 'field': 'my_field'} ] ``` -------------------------------- ### Configure Nplusone to Raise Errors (Django/Flask) Source: https://github.com/jmcarp/nplusone/blob/master/README.rst Set NPLUSONE_RAISE to True to make nplusone raise an NPlusOneError when unnecessary queries are detected. This is useful for failing automated tests. ```python # Django config NPLUSONE_RAISE = True ``` ```python # Flask config app.config['NPLUSONE_RAISE'] = True ``` -------------------------------- ### Django n+1 Query Detection Source: https://github.com/jmcarp/nplusone/blob/master/README.rst When data is loaded lazily, nplusone emits a log message indicating a potential n+1 query. Consider using select_related or prefetch_related. ```text Potential n+1 query detected on `.` ``` -------------------------------- ### Configure nplusone Notifiers (Django/Flask) Source: https://context7.com/jmcarp/nplusone/llms.txt Enable LogNotifier or ErrorNotifier by setting NPLUSONE_LOG or NPLUSONE_RAISE to True in your Django settings or Flask app.config. You can also specify a custom logger or exception class. ```python import logging from nplusone.core import exceptions # --- Django settings.py --- NPLUSONE_LOG = True # enable LogNotifier (default) NPLUSONE_LOGGER = logging.getLogger('myapp.nplusone') NPLUSONE_LOG_LEVEL = logging.WARNING NPLUSONE_RAISE = True # enable ErrorNotifier NPLUSONE_ERROR = exceptions.NPlusOneError # default; can be a custom exception # --- Flask app.config equivalent --- app.config.update({ 'NPLUSONE_LOG': True, 'NPLUSONE_LOGGER': logging.getLogger('myapp.nplusone'), 'NPLUSONE_LOG_LEVEL': logging.WARNING, 'NPLUSONE_RAISE': True, 'NPLUSONE_ERROR': exceptions.NPlusOneError, }) ``` ```python # --- Custom exception example --- class QueryPerformanceError(Exception): """Raised when nplusone detects a query performance problem.""" app.config['NPLUSONE_ERROR'] = QueryPerformanceError ``` ```python # In tests, assert the custom exception is raised: import pytest def test_detects_n_plus_one(client): with pytest.raises(QueryPerformanceError): client.get('/endpoint-with-lazy-load') ``` -------------------------------- ### Whitelist Models by Pattern (Django) Source: https://github.com/jmcarp/nplusone/blob/master/README.rst Use fnmatch patterns in the Django NPLUSONE_WHITELIST to ignore notifications for a group of models. ```python # Django config NPLUSONE_WHITELIST = [ {'model': 'myapp.*'} ] ``` -------------------------------- ### Fix N+1 Queries in Flask with Subqueryload Source: https://context7.com/jmcarp/nplusone/llms.txt Demonstrates how to fix N+1 query issues in Flask by using `subqueryload` to fetch related data efficiently. This avoids lazy loading for each item in a collection. ```python from flask import Flask, jsonify from flask_sqlalchemy import SQLAlchemy app = Flask(__name__) app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///:memory:' db = SQLAlchemy(app) # Assume User model with a 'hobbies' relationship is defined elsewhere # class User(db.Model): # id = db.Column(db.Integer, primary_key=True) # hobbies = db.relationship('Hobby', backref='user') # class Hobby(db.Model): # id = db.Column(db.Integer, primary_key=True) # name = db.Column(db.String) # user_id = db.Column(db.Integer, db.ForeignKey('user.id')) @app.route('/users') def users(): users = User.query.all() # BAD: accesses user.hobbies for each user → n+1 return jsonify([{'id': u.id, 'hobbies': [h.name for h in u.hobbies]} for u in users]) # → NPlusOneError: "Potential n+1 query detected on `User.hobbies`" @app.route('/users-fixed') def users_fixed(): # GOOD: subqueryload fetches hobbies in one extra query users = User.query.options(db.subqueryload('hobbies')).all() return jsonify([{'id': u.id, 'hobbies': [h.name for h in u.hobbies]} for u in users]) ``` -------------------------------- ### Django Unnecessary Eager Load Detection Source: https://github.com/jmcarp/nplusone/blob/master/README.rst When related data is eagerly loaded but not accessed, nplusone logs a warning about a potential unnecessary eager load. ```text Potential unnecessary eager load detected on `.` ``` -------------------------------- ### Low-Level Signal Suppression with signals.ignore Source: https://context7.com/jmcarp/nplusone/llms.txt Utilize `nplusone.core.signals.ignore` to disconnect specific Blinker signal receivers for the current thread. This provides fine-grained control, similar to `NPlusOne.ignore` but at a lower level. ```python from nplusone.core import signals import nplusone.ext.sqlalchemy # Suppress lazy_load detection for a specific code section with signals.ignore(signals.lazy_load): users = session.query(User).all() addresses = [u.addresses for u in users] # lazy loads — no notification # Suppress unused eager load detection with signals.ignore(signals.eager_load): users = session.query(User).options( sqlalchemy.orm.joinedload('hobbies') ).all() ids = [u.id for u in users] # hobbies loaded but not accessed — no warning # Available signals: # signals.lazy_load — fired when a relationship is loaded lazily # signals.eager_load — fired when a relationship is loaded eagerly # signals.load — fired when a queryset fetches multiple rows # signals.touch — fired when an already-loaded relationship is accessed # signals.ignore_load — fired for single-record fetches (get/one) to suppress false positives ``` -------------------------------- ### Ignore Notifications Locally with Context Manager Source: https://github.com/jmcarp/nplusone/blob/master/README.rst Use the signals.ignore context manager to temporarily suppress nplusone notifications for specific operations, such as lazy loading. ```python from nplusone.core import signals with signals.ignore(signals.lazy_load): # lazy-load rows # ... ``` -------------------------------- ### Temporarily Ignore NPlusOne Warnings in Flask Source: https://context7.com/jmcarp/nplusone/llms.txt Use the `nplusone.ignore` context manager to temporarily disable NPlusOne warnings for specific code blocks. This is useful when lazy loading is intentional and acceptable. ```python from flask import g, Flask, jsonify from nplusone.ext.flask_sqlalchemy import NPlusOne app = Flask(__name__) nplusone = NPlusOne() @app.route('/report') def report(): # Suppress lazy_load warnings for this specific block only with nplusone.ignore('lazy_load'): users = User.query.all() result = [u.addresses for u in users] # lazy load — no warning emitted return jsonify({'count': len(result)}) # Also available: 'eager_load' signal name with nplusone.ignore('eager_load'): items = Order.query.options(db.joinedload('lines')).all() summary = [o.id for o in items] # eager load never accessed — no warning ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.