🌐 Italiano — queryset and model rules (DOL001–DOL008, DOL011–DOL015)
🌐 Tiếng Việt — queryset rules (DOL001–DOL007)
ORM Lens ships two rule surfaces:
DOL###) — 18 line-oriented static checks that run inside the VS Code extension on every .py file. Findings appear in the Problems panel under the source ORM Lens, link to these pages from the diagnostic code, and — where a fix is safe to express as a text edit — carry a QuickFix lightbulb. Detection is regex-based with bounded windows; no Python process is involved.pip install orm-lens) for terminals and pipelines: migration-risk, nplusone, blast-radius — which joins migration risks with the code that still references what they change — and drift, a makemigrations --check that needs no Django boot.Severity mirrors VS Code’s four diagnostic levels: error, warning, info, hint. Every rule has a default (listed below); override per rule in .vscode/settings.json via djangoOrmLens.rules — e.g. {"djangoOrmLens.rules": {"DOL013": "error", "DOL007": "off"}}.
Applicability follows Clippy’s semantics. It is a property of each individual finding and gates whether an editor may apply the fix unattended:
| Applicability | Meaning |
|---|---|
safe |
Semantically equivalent, always correct to apply. Eligible for auto-apply and “Fix All”. |
suggestion |
Usually right but may need review — offered as a QuickFix, never included in “Fix All”. |
unsafe |
Likely-correct but breaks in edge cases — surfaced as a diagnostic only, never auto-applied. |
| Code | Rule | Category | Default severity | Applicability |
|---|---|---|---|---|
| DOL001 | Prefer .exists() over .count() > 0 |
queryset | info | safe |
| DOL002 | Prefer not .exists() over .count() == 0 |
queryset | info | safe |
| DOL003 | Prefer not .exists() over .first() is None |
queryset | info | safe |
| DOL004 | Prefer .exists() over .first() is not None |
queryset | info | safe |
| DOL005 | Consider Q(...) over .filter().exclude() chain |
queryset | hint | suggestion |
| DOL006 | Drop list() around a QuerySet in for-loop |
queryset | info | safe |
| DOL007 | Possible N+1: attribute access inside for-loop | queryset | warning | unsafe |
| DOL008 | Field name in a lookup looks misspelled | correctness | warning | suggestion |
| DOL011 | null=True on CharField/TextField |
model | warning | suggestion |
| DOL012 | Model without __str__ method |
model | info | suggestion |
| DOL013 | ForeignKey or OneToOneField without on_delete |
model | error | suggestion |
| DOL014 | CharField without max_length |
model | error | suggestion |
| DOL015 | TextField with max_length has no DB effect |
model | hint | suggestion |
| DOL021 | datetime.now() should be timezone.now() |
datetime | warning | suggestion |
| DOL022 | datetime.utcnow() is deprecated |
datetime | warning | suggestion |
| DOL031 | render() with locals() as context |
forms | warning | suggestion |
| DOL032 | fields = '__all__' in Meta |
forms | warning | unsafe |
| DOL041 | Planner setting overridden in raw SQL | raw SQL | warning | unsafe |
# orm-lens-disable-next-line DOL007 (next line; comma-separate for several codes)
qs.count() > 0 # orm-lens-disable-line DOL001
# orm-lens-disable DOL011 (own line — disables for the rest of the file)
Ruff-style bulk selection is also available: djangoOrmLens.rulesSelect (e.g. ["DOL0"]) and djangoOrmLens.rulesIgnore (e.g. ["DOL03"]).
These run from the Python CLI, not the editor. Both exit non-zero on findings (see each page for exact semantics) and emit --format sarif (SARIF 2.1.0 for GitHub Code Scanning) or --format github (workflow commands for zero-setup PR annotations).
<app>/migrations/*.py flagging operations that are dangerous on production databases. Run with orm-lens migration-risk.select_related / prefetch_related. Run with orm-lens nplusone.scan, er and nplusone also read SQLAlchemy 2.0 / 1.x, Flask-SQLAlchemy and SQLModel models; nplusone flags lazy relationship() reads in loops without selectinload / joinedload.