Query Ignore¶
The .queryignore file lets you suppress specific django-query-doctor findings. This is useful for known issues that you plan to fix later, third-party code you cannot modify, or intentional patterns that are not actually problems.
Setup¶
Create a .queryignore file in your project root (the same directory as manage.py):
django-query-doctor checks for this file automatically. No settings changes are needed.
Syntax¶
Each line in .queryignore specifies a file pattern and an analyzer name, separated by whitespace:
# Syntax: file_pattern analyzer_name
myapp/views.py nplusone
myapp/serializers.py duplicate
This suppresses:
- All N+1 prescriptions originating from
myapp/views.py. - All duplicate query prescriptions originating from
myapp/serializers.py.
Wildcards¶
Standard glob wildcards are supported in file patterns:
# All files in the legacy app
legacy_app/* nplusone
legacy_app/* duplicate
# All serializers in any app
*/serializers.py drf_serializer
# All Python files in a specific directory
reports/**/*.py fat_select
# A specific file, all analyzers
myapp/views.py *
| Pattern | Matches |
|---|---|
myapp/views.py |
Exactly myapp/views.py |
myapp/*.py |
All .py files directly in myapp/ |
myapp/**/*.py |
All .py files in myapp/ and subdirectories |
*/views.py |
views.py in any top-level app directory |
* (as analyzer) |
All analyzers |
Comments¶
Lines starting with # are comments. Blank lines are ignored:
# Known N+1 in the legacy dashboard — will fix in Q3
dashboard/views.py nplusone
# Third-party integration we cannot modify
vendor/api_client.py *
# Intentional: we want SELECT * here for caching
cache/warmers.py fat_select
Analyzer Names¶
Use the analyzer's name attribute as the second field:
| Analyzer Name | What It Detects |
|---|---|
nplusone |
N+1 query patterns |
duplicate |
Duplicate queries |
missing_index |
Missing database indexes |
fat_select |
Unnecessary SELECT * |
queryset_eval |
Redundant queryset evaluations |
drf_serializer |
N+1 in DRF serializers |
query_complexity |
Overly complex queries |
* |
All analyzers |
For custom analyzers, use the name specified in the analyzer's name class attribute.
Examples¶
Suppress a Known N+1 in a Legacy View¶
Suppress All Issues in Generated Code¶
Suppress Duplicate Queries in Tests¶
Suppress Missing Index Warnings for Small Tables¶
How Matching Works¶
When django-query-doctor generates a prescription, it checks the prescription's location (file path) against each line in .queryignore:
- The file path from the prescription is made relative to the project root.
- Each
.queryignoreentry's file pattern is matched against this relative path using glob matching. - If the file pattern matches and the analyzer name matches (or is
*), the prescription is suppressed.
Suppressed prescriptions are not shown in console output, not included in JSON reports, and do not cause --fail to trigger.
Viewing Suppressed Issues¶
To see what is being suppressed, use the --show-ignored flag with any management command:
This prints suppressed prescriptions separately, so you can review whether your ignore rules are still appropriate.
Use Sparingly¶
Warning: The
.queryignorefile should be a temporary measure, not a permanent fix. Every entry represents a known performance issue in your codebase. Review it regularly and remove entries as issues are resolved.
Best practices:
- Add a comment explaining why each entry exists and link to a tracking issue.
- Review periodically -- include
.queryignorereview in your sprint/quarterly planning. - Prefer fixing over ignoring. Use the Auto-Fix system to resolve common issues quickly.
- Do not ignore entire directories unless they truly contain only code you cannot modify (third-party, generated).
Further Reading¶
- CI Integration -- How
.queryignoreinteracts with CI pipelines. - Auto-Fix -- Fix issues instead of ignoring them.
- Custom Plugins -- Custom analyzers respect
.queryignoreautomatically.