DjangoおよびSQLAlchemyのモデルに対して静的解析を行い、データベースなしでN+1クエリ、マイグレーションのリスク、スキーマのリレーションシップを検出します。
別名 FROWNINGdev/django-orm-lens, django-orm-lens
- スター
- 106
- ツール
- —
- ダウンロード数(30日間)
- 699
- 最新バージョン
- 1.15.0
- 最終コミット
- 2026年11月11日
- ライセンス
- MIT
ORM Lens MCPとは
ORM LensはMCPサーバーです。 DjangoおよびSQLAlchemyのモデルに対して静的解析を行い、データベースなしでN+1クエリ、マイグレーションのリスク、スキーマのリレーションシップを検出します。.
プロジェクトのREADMEから生成された概要
ORM Lens MCP server について
Django ORM Lensは、DjangoおよびSQLAlchemyのモデルに対して静的解析を提供し、実行中のデータベース、動作する仮想環境、またはsettingsモジュールを必要とせずにデータベース関連の問題を特定します。モデルとマイグレーションを直接解析してインサイトを生成するため、ローカル開発、CIパイプライン、またはAIエージェント経由での利用に適しています。開発者はこれを使用して、ER図を通じてスキーマのリレーションシップを可視化したり、潜在的なパフォーマンスのボトルネックを検出したりできます。
このツールは、N+1クエリの検出、マイグレーションリスクの評価、スキーマドリフトの検出など、いくつかの特化した機能を提供します。AI主導のワークフロー向けに、MCP serverは14個の読み取り専用ツールを提供し、エージェントが信頼できるデータを使用してスキーマに関する質問に回答できるようにします。VS CodeやCursorなどのエディタに統合したり、uvxやpipを使用してコマンドラインから実行したり、Dockerコンテナを使用してデプロイしたりできます。ORM_LENS_ROOTをプロジェクトパスに指定することで、クローン直後の環境や壊れた環境でも動作するように設計されています。
できること
- 1N+1クエリのループ検出非効率なデータベースアクセスパターンを特定し、修正に必要なselect_relatedやselectinloadの呼び出しを見つけます。
- 2マイグレーションリスクの評価DjangoのマイグレーションやAlembicのリビジョンを分析し、テーブルのロックや失敗を引き起こす可能性のある操作を見つけます。
- 3AIエージェントによるスキーマクエリ静的解析を使用して、データベーススキーマに関する特定の質問に回答する機能をAIエージェントに提供します。
- 4マイグレーションの影響評価破壊的なマイグレーションの影響範囲や、特定のフィールドを削除した際のレイヤーを跨いだ影響を判断します。
プロジェクトの README から作成されています。すべてのユースケースは、その引用と照らし合わせて確認されています。
ORM Lens MCPのインストール方法
フォーマット検証日 2026年11月10日Cursor に追加Gooseに追加Claude CodeにORM Lens MCPをインストール
$ claude mcp add django-orm-lens -- uvx django-orm-lensCursorにORM Lens MCPをインストール
~/.cursor/mcp.json
{
"mcpServers": {
"django-orm-lens": {
"command": "uvx",
"args": [
"django-orm-lens"
]
}
}
}VS CodeにORM Lens MCPをインストール
.vscode/mcp.json
{
"servers": {
"django-orm-lens": {
"type": "stdio",
"command": "uvx",
"args": [
"django-orm-lens"
]
}
}
}VS Code CLIにORM Lens MCPをインストール
$ code --add-mcp '{"name":"django-orm-lens","type":"stdio","command":"uvx","args":["django-orm-lens"]}'Claude DesktopにORM Lens MCPをインストール
claude_desktop_config.json
{
"mcpServers": {
"django-orm-lens": {
"command": "uvx",
"args": [
"django-orm-lens"
]
}
}
}CodexにORM Lens MCPをインストール
$ codex mcp add django-orm-lens -- uvx django-orm-lensCodex config.tomlにORM Lens MCPをインストール
~/.codex/config.toml
[mcp_servers.django-orm-lens] command = "uvx" args = ["django-orm-lens"]
Gemini CLIにORM Lens MCPをインストール
$ gemini mcp add -s user django-orm-lens uvx -- django-orm-lensGemini settings.jsonにORM Lens MCPをインストール
~/.gemini/settings.json
{
"mcpServers": {
"django-orm-lens": {
"command": "uvx",
"args": [
"django-orm-lens"
]
}
}
}設定
ORM_LENS_ROOT
| 名前 | 説明 | 種類 |
|---|---|---|
| ORM_LENS_ROOT | — |
自動チェック
実行日 2026年11月12日完全なレポート →自動チェックに合格しました。これはセキュリティ監査ではありません。コードを読み、サーバーに必要最小限のアクセス権を与えてください。 チェックの仕組み
- ソースリポジトリがリンクされており、アクセス可能合格
- オープンソースライセンス (OSI)合格
- 過去1年以内にコミットまたはリリースあり合格
- パッケージ名が有名なパッケージに酷似していない合格
- リモートエンドポイントがHTTPSを使用未チェック
- 破壊的なツールがラベル付けされている未チェック
- モデルへの隠れた指示がない合格
- パッケージおよびその依存関係に重大な勧告なし合格
README
GitHubで見るEnglish · Русский · Español · 中文
ORM Lens
ER diagrams, N+1 detection and migration-risk checks for Django and SQLAlchemy — without booting either.
Your entire model graph — live in your editor sidebar, gating your CI, and answering your AI agent over MCP. All from static parsing: no database, no runserver, no working venv. Django models and migrations, SQLAlchemy models and Alembic revisions.
Formerly django-orm-lens. pip install django-orm-lens still works and installs orm-lens.
Replaces: graph_models + django-schema-graph + hand-drawn ER diagrams + grep archaeology.
Featured in Django News #347 · PyCoder's Weekly #746
⚡ 10 seconds to first insight
uvx orm-lens scan -f table # every app and model at a glance
uvx orm-lens nplusone # N+1 loops, with the select_related / selectinload to add
uvx orm-lens migration-risk # Django migrations and Alembic revisions that lock tables or fail
Cold clone, broken venv, no settings module — you still see every app and model of the project, then the N+1 loops and risky migrations in it, right in your terminal. (uvx is from uv; pipx run works the same way.)
Then pick your surface — three distributions, one parser core:
| You are | Install | You get |
|---|---|---|
| Editor user (Django) — VS Code / Cursor / Windsurf / VSCodium | code --install-extension frowningdev.django-orm-lens |
Field autocomplete in .filter(), sidebar tree, live ER diagram, hover cards, 18 lint rules with QuickFixes |
| Terminal / CI user | pip install orm-lens |
17 subcommands, SARIF + PR annotations, pre-commit hooks, a GitHub Action |
| AI-agent user — Cursor / Claude Code / Aider / Zed / Continue | pip install "orm-lens[mcp]" |
14 read-only MCP tools answering schema questions from ground truth |
MCP setup is one JSON block — see Integrations. Point ORM_LENS_ROOT at your project's absolute path.
🆓 Paid-tier capabilities, free and MIT
Schema review is a paid category nearly everywhere. A bot that reviews every pull request, analysis that follows a queryset past the function it was built in, a check that catches schema drift, index advice grounded in real table statistics — those normally sit behind a per-seat or per-database subscription.
All of it is here, MIT-licensed, with no tier gate, no seat count, no account, and no telemetry:
| Capability usually sold as a paid tier | Here |
|---|---|
| PR review bot for schema changes — posts once, then updates in place | blast-radius + the Action |
| Analysis that follows a queryset across functions | nplusone |
| Schema drift detection | drift |
| Index proposals from observed QuerySet usage | suggest-indexes |
| Migration risk weighed against real table sizes | blast-radius --stats |
| Blast radius of a destructive migration | blast-radius |
| Cross-layer impact of removing a field | impact |
There is no Pro tier, and none is planned. If the tool saves you an afternoon, a star is the entire ask.
📊 Traction
If the tool saves you a
grepnext time you touch a strange Django project — a star helps others find it.
📈 Star growth
⚡ Install
VS Code / Cursor / Windsurf (VS Code Marketplace):
code --install-extension frowningdev.django-orm-lens
VSCodium / code-server / Gitpod / any OSS Code fork (Open VSX):
codium --install-extension frowningdev.django-orm-lens
Or search ORM Lens in the Extensions view — same publisher frowningdev on both registries.
Terminal & AI coding agents:
pip install orm-lens # CLI only
pip install "orm-lens[mcp]" # + MCP server for AI agents
Requires Python 3.9+ (the MCP server: 3.10+). Zero runtime dependencies for the CLI.
Docker (v0.6+):
docker run --rm -v "$PWD:/workspace" ghcr.io/frowningdev/orm-lens scan --path .
Multi-arch (amd64 + arm64). No Python required on the host. Good for CI and one-off audits.
🎯 The problem
Works offline. Works on a broken venv. Works on someone else's laptop. Works in CI.
You open a Django project. It has 20 apps. You need to answer a simple question:
"Which app owns the
Ordermodel, and how is it connected toUser?"
Today, that means: Ctrl+P, "models", scroll through 30 hits, open five files, Ctrl+F for class Order, read through 400 lines of ForeignKey('otherapp.Something') strings, try to remember what you learned two files ago.
Half a day gone. Every time. On every project.
✨ With ORM Lens
📚 A tree of everything
Every app → every model → every field → every Meta option. Grouped by application, sorted alphabetically, expandable.
Icons distinguish CharField from ForeignKey from ManyToManyField at a glance.
🕸️ A live ER diagram
One command opens a Mermaid entity-relationship diagram of your entire schema. Watch it redraw as you edit. Export to SVG.
ForeignKey, OneToOneField, and ManyToManyField become proper cardinality arrows.
🔎 Hover for relations
Hover over ForeignKey('app.Model') in any Python file → a card pops up with the target model's fields, relations, and a "Jump to" link. No Ctrl+F, no file dialog.
🧭 Jump-to-definition
Click any field in the tree → cursor lands on the exact line. Filter the tree by app or model name. Split models/ packages are fully supported.
⚡ Zero configuration
No DJANGO_SETTINGS_MODULE. No runserver. Parses models.py statically. Works with a broken venv, a missing dependency, or on someone else's laptop.
🎨 Native VS Code UI
Dark theme. Light theme. Your theme. Follows your icon theme, your font, your key bindings. Nothing garish, nothing branded.
🚀 Power features
💥 Blast radius
The review-time question a schema change actually raises: what does this hit? Every destructive migration operation becomes a target carrying its risks, every place in the codebase that still reads it, and — for whole-model operations — the cascade fallout.
migration-risk, impact and cascade each answer a third of that; nobody joins them by hand, so the tool does. --format markdown is a postable PR comment; --stats turns "probably populated" into ~41 000 000 rows, 12.0 GB from a read-only query you run yourself, with no database credential anywhere near CI.
🧭 Schema drift
makemigrations --check without booting Django. Each app's migrations are replayed in order into the field set they imply, then compared against what models.py declares.
Django's own check needs a working settings module, an importable app registry and every dependency installed — unavailable on a cold clone or a broken venv, which is exactly when the answer is cheapest to act on. Only the dangerous direction fails the build: a field declared but never migrated means the column will not exist, and the first query touching it errors.
🎯 Inline diagnostics & QuickFixes (18 rules)
Static analysis over .py files with Ruff-style codes (DOL001..DOL041), Clippy-style Applicability, and per-rule severity overrides. .count() > 0 → .exists(), null=True on CharField, missing on_delete, datetime.now() → timezone.now(), planner-GUC overrides in raw SQL (enable_*, plan_cache_mode, jit*; diagnostic-only), and a dozen more.
Suppress inline with # orm-lens-disable-next-line DOL007.
🧪 Factory generator
Right-click any model → factory_boy DjangoModelFactory scaffold with Faker providers keyed by field type. CharField(max_length) scales word-count buckets, DecimalField(N,D) computes left_digits=N-D, choices= maps to Iterator, M2M gets @post_generation. FK chains pull related factories transitively.
Also available as CodeLens above each model class.
🕰 Time-Travel Schema Diff
Pick a models.py, pick two commits, get a typed diff as PR-ready markdown. AddModel / DropModel / RenameModel / ModifyModel events with confidence-scored rename detection (Levenshtein + field-shape Jaccard).
Renames are first-class events, never Add + Drop. Blob-SHA LRU cache — commits that don't touch models.py share their parsed snapshot.
🔎 Impact analysis
"What breaks if I remove this field?" — right-click a field or model → workspace-wide scan grouped by Django layer (models, serializers, forms, admin, views, urls, templates, tests, migrations).
Findings carry a Certain / Likely / Possibly confidence tag. Handles ORM string refs (order_by("-author")), kwarg lookups (filter(author__id=1)), Meta.fields tuples, and template variables.
⚡ Interactive query builder
Right-click a field or model → pick a template → snippet inserted at cursor (with tab-stops) or in a fresh untitled buffer.
.filter(field=?) on an FK auto-appends .select_related(...), .annotate(post_count=Count('post_set')) honours related_name, .prefetch_related for M2M, .values('field').distinct(), .only('field').
🎨 Sidebar UX overhaul
Stable TreeItem.id — refresh no longer collapses the tree. Rich MarkdownString tooltips with command: deep-links. Activity-bar badge counts DOL### issues.
FileDecorationProvider badges: red ! on FK-without-on_delete, yellow ~ on null=True string fields (bubbles up to the parent Model row, Git-style).
📸 What it looks like
Live sample — real orm-lens er output, rendered by GitHub right here:
erDiagram
User {
CharField display_name
}
Tag {
CharField name
}
Post {
CharField title
DateTimeField created_at
}
Comment {
TextField body
}
Post }o--|| User : "author [CASCADE, as posts]"
Post }o--o{ Tag : "tags [as posts]"
Comment }o--|| Post : "post [CASCADE, as comments]"
Comment }o--|| User : "author [SET_NULL]"
Also included in the extension:
- 🕸️ Live ER diagram — Mermaid cardinality arrows, edge labels (
CASCADE,through Model,as related_name), theme-aware, one-click SVG export - 🔎 Hover cards — over any
ForeignKey('app.Model')orManyToManyField(...), with a one-click jump link - 🧭 CodeLens — above every
class Modelline: field count, relation count, and an Open ER diagram action - 🎨 Named themes —
auto/default/dark/forest/neutralfor the diagram webview
🧪 SQLAlchemy, FastAPI and Flask (preview)
The CLI and the MCP server read SQLAlchemy projects the same way they read Django ones: parsed with ast, never imported, no database.
uvx orm-lens scan -f table # SQLAlchemy 2.0 / 1.x, Flask-SQLAlchemy and SQLModel models
uvx orm-lens er -f mermaid # ER diagram from the foreign keys and many-to-many tables
uvx orm-lens nplusone # lazy relationship() reads in loops, with the selectinload to add
uvx orm-lens migration-risk # Alembic revisions: NOT NULL without server_default, locking indexes, multiple heads
app/views.py:12 [high] loop=user qs=users
accessed: addresses
fix: .options(selectinload(User.addresses))
Tuned against Superset, Airflow, Prefect, Polar, Dispatch, Mealie, CTFd, Redash and the FastAPI template: 517 models read, and every N+1 finding on them checked by hand and real. Details: SQLAlchemy models · Alembic rules. The VS Code extension is Django-only for now.
🤖 For terminals and AI coding agents
The same parser that powers the VS Code extension ships as a standalone Python package — with an optional MCP (Model Context Protocol) server so any MCP-compatible AI agent can navigate your Django schema without importing Django or booting your app.
CLI
orm-lens scan -f json # every app, every model, every field
orm-lens describe blog.Post # one model in Markdown
orm-lens list | fzf # flat app.Model — pipes anywhere
orm-lens er > schema.mmd # ER diagram — Mermaid (default)
orm-lens er -f dbml > schema.dbml # …or DBML: paste into dbdiagram.io
orm-lens er -f d2 > schema.d2 # …or D2 / plantuml / dot
orm-lens diff before.json after.json # what a PR changes structurally
orm-lens nplusone --format github # N+1 findings as PR annotations
orm-lens migration-risk -f sarif # SARIF for GitHub Code Scanning
orm-lens migration-risk --path api/ # Alembic revisions too (FastAPI, Flask)
orm-lens suggest-indexes blog.Post # Meta.indexes proposals from usage
orm-lens signals # sender→signal→handler graph
orm-lens migration-deps blog -f mermaid # per-app migration DAG
orm-lens cascade blog.Author # what one delete() takes down
orm-lens impact author # what still references a field
orm-lens blast-radius -f markdown # risks + who still reads them
orm-lens drift # migrations vs models, no boot
orm-lens stats-sql # read-only SQL for --stats
impact,blast-radius,driftandstats-sqlship in py-1.7.0 and later.
Alembic (preview):
migration-riskalso checks Alembic revisions — NOT NULL withoutserver_default, indexes withoutCONCURRENTLY, multiple heads and nine more rules — so SQLAlchemy projects without Django (FastAPI, Flask) get the same static migration review.
Django 6.1:
on_delete=models.DB_CASCADEdeletes child rows in the database, so theirpost_deletehandlers never run. Since py-1.13.8,cascadenames the handlers eachDB_CASCADErelation skips — why that matters and what to do.
Every command accepts --path <dir> and --exclude <glob>. nplusone / migration-risk / diff exit code 1 on findings — drop them into CI to block PRs on regressions.
MCP server
Register it once with your agent and it exposes fourteen read-only tools:
| Tool | Purpose |
|---|---|
list_apps |
Every Django app in the workspace with model counts |
list_models |
Flat app.Model list, optional app filter |
describe_model |
Full field / relation / Meta detail for one model |
find_relations |
Inbound + outbound relations for one model |
cascade_preview |
Blast radius of one delete(), grouped by on_delete, plus the post_delete receivers Django 6.1's DB_CASCADE skips |
er_diagram |
ER diagram — mermaid / dbml / d2 / plantuml / dot |
describe_migration_dependency |
Per-app migration DAG: roots, leaves, cross-app deps |
suggest_indexes |
Meta.indexes proposals from observed QuerySet usage |
signal_graph |
Sender→signal→handler graph from @receiver decorators and signal.connect() calls |
migration_risk |
Dangerous schema changes in Django migrations & Alembic revisions (table locks, dropped columns) |
blast_radius |
What a destructive migration hits: its risks, the code still reading it, the cascade fallout |
drift |
makemigrations --check without booting Django — migrations diffed against models.py |
impact |
Every reference to a field or model name, grouped by Django layer |
nplusone_scan |
Static N+1 findings for the whole workspace |
# Start it directly
orm-lens-mcp
ORM Lens MCPのよくある質問
ORM Lens MCPをClaude Codeに追加するには
ターミナルでclaude mcp add django-orm-lens -- uvx django-orm-lensを実行します。すべてのプロジェクトで利用するには--scope userを追加します。
ORM Lens MCPをCursorに追加するには
~/.cursor/mcp.jsonを開き、上記のインストールセクションに示すCursor設定を使ってmcpServersの下にサーバーを追加します。
実行中のデータベースや環境は必要ですか?
いいえ、静的解析を使用しているため、データベース、実行中のサーバー、または動作する仮想環境がなくても動作します。
このMCP serverはAIエージェントにどのような機能を提供しますか?
このMCP serverは14個の読み取り専用ツールを提供し、AIエージェントが信頼できるソース(ground truth)に基づいてデータベーススキーマに関する質問に回答できるようにします。
どのORMがサポートされていますか?
DjangoモデルとSQLAlchemyモデルの両方をサポートしています。