LibCST-based linting rules for DRF serializers — detects ORM queries causing N+1
Project description
mitol-drf-lint
LibCST-based linting rules for Django REST Framework serializers. Detects Django ORM queries executed inside DRF serializer methods, which cause N+1 query bugs.
Rules
| Rule | Description |
|---|---|
ORM001 |
Django ORM manager access (.objects.) inside a serializer method |
ORM002 |
Related-manager queryset call (instance.children.filter() etc.) inside a serializer method |
Installation
pip install mitol-drf-lint
Usage
# Check specific files
drf-lint path/to/serializers.py
# Check all serializers in a project
drf-lint $(find . -name "serializers.py" -not -path "*/migrations/*")
# Generate a baseline to suppress existing violations (for gradual rollout)
drf-lint --generate-baseline --baseline drf_lint_baseline.json path/to/serializers.py
# Subsequent runs ignore violations present in the baseline
drf-lint --baseline drf_lint_baseline.json path/to/serializers.py
Exit code is 0 when no new violations are found, 1 when violations are detected.
pre-commit Integration
In this repo (local)
- repo: local
hooks:
- id: drf-serializer-orm-check
name: DRF Serializer ORM Check
entry: drf-lint
language: python
files: "serializers\\.py$"
From other repos
- repo: https://github.com/mitodl/ol-django
rev: <commit-sha-or-tag>
hooks:
- id: drf-serializer-orm-check
Suppressing individual violations
Add # noqa: ORM001 or # noqa: ORM002 at the end of the offending line, or
# noqa to suppress all rules on that line:
def get_image(self, instance):
item = instance.children.order_by("position").first() # noqa: ORM002
How it works
The checker uses LibCST to parse Python source files into a concrete syntax tree and walks the tree looking for:
- Serializer classes: any class whose name ends in
Serializeror that inherits from a class containingSerializer. - Inside methods of those classes: any
Callnode matching ORM patterns.
ORM001 pattern: attribute chain containing .objects (Django model manager),
e.g. User.objects.filter(...).
ORM002 pattern: queryset method call on a multi-level attribute access,
e.g. instance.children.all(), instance.resource_prices.filter(...).
Methods inside inner classes (e.g. class Meta) are not checked.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mitol_drf_lint-2026.4.2.tar.gz.
File metadata
- Download URL: mitol_drf_lint-2026.4.2.tar.gz
- Upload date:
- Size: 7.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8e4ba0e518f0f37016a00e9ed6b72e2d1645b750d79da695192a8ef49460c37
|
|
| MD5 |
d7f65ef2362e08961a8ce55ea0b54353
|
|
| BLAKE2b-256 |
7ff3a4f6c2556efd3605425be21f71c8b27a4cafebebb269875b607faaefb285
|
File details
Details for the file mitol_drf_lint-2026.4.2-py3-none-any.whl.
File metadata
- Download URL: mitol_drf_lint-2026.4.2-py3-none-any.whl
- Upload date:
- Size: 11.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
dec795ab47ba0f983e13b2af19eb6842a6c6fd24c244fbd20be68a6211f21588
|
|
| MD5 |
529b6a1cb6b2a96e045a7931496bdc88
|
|
| BLAKE2b-256 |
595c0d25ae042b082a404eaef88ae8f177b2c5d570121f3bc575636e280a6016
|