Skip to main content

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:

  1. Serializer classes: any class whose name ends in Serializer or that inherits from a class containing Serializer.
  2. Inside methods of those classes: any Call node 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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

mitol_drf_lint-2025.3.27.tar.gz (6.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

mitol_drf_lint-2025.3.27-py3-none-any.whl (10.8 kB view details)

Uploaded Python 3

File details

Details for the file mitol_drf_lint-2025.3.27.tar.gz.

File metadata

  • Download URL: mitol_drf_lint-2025.3.27.tar.gz
  • Upload date:
  • Size: 6.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.3

File hashes

Hashes for mitol_drf_lint-2025.3.27.tar.gz
Algorithm Hash digest
SHA256 1e6c872bb4bd198c262be045cabe522a00ad83d9ed7fdd53c8049b9bb2138787
MD5 42428116ea4313d84c7db8dbe0e5d136
BLAKE2b-256 86255dde18a64b612a1e0c68d0617436745d91c1499573c6c80d32f92344ef77

See more details on using hashes here.

File details

Details for the file mitol_drf_lint-2025.3.27-py3-none-any.whl.

File metadata

File hashes

Hashes for mitol_drf_lint-2025.3.27-py3-none-any.whl
Algorithm Hash digest
SHA256 76467eb7b6250093ccf631f87ebc3265155997e486be49d11ee3a7b20bad2fd1
MD5 43a3992dc97efbf83dc7d623f6b2918b
BLAKE2b-256 607276c9a413a7376c4be572edf81623d5ce950ad5de5c65713675c6b2df33ff

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page