Django ORM Lens
Análisis estático de esquemas Django para agentes de IA: 10 herramientas de solo lectura (modelos, relaciones, diagramas ER, DAG de migraciones, escaneo N+1) sin base de datos y sin arranque de Django.
Documentación
English · Русский · Español · 中文
Django ORM Lens
Diagramas ER, detección de N+1 y comprobaciones de riesgo de migración para Django — sin iniciarlo.
Todo tu grafo de modelos — en vivo en la barra lateral de tu editor, controlando tu CI y respondiendo a tu agente de IA a través de MCP. Todo desde análisis estático: sin base de datos, sin runserver, sin venv funcional.
Reemplaza: graph_models + django-schema-graph + diagramas ER dibujados a mano + arqueología con grep.
Destacado en Django News #347 · PyCoder's Weekly #746
⚡ 10 segundos hasta la primera idea
uvx django-orm-lens scan -f table # every app and model at a glance
uvx django-orm-lens nplusone # N+1 loops, with the select_related to add
uvx django-orm-lens migration-risk # migrations that lock tables or fail on existing rows
Clon en frío, venv roto, sin módulo de configuración — aún así ves cada app y modelo del proyecto, luego los bucles N+1 y las migraciones arriesgadas, directamente en tu terminal. (uvx es de uv; pipx run funciona igual.)
Luego elige tu superficie — tres distribuciones, un núcleo de análisis:
| Eres | Instalación | Obtienes |
|---|---|---|
| Usuario de editor — VS Code / Cursor / Windsurf / VSCodium | code --install-extension frowningdev.django-orm-lens | Autocompletado de campos en .filter(), árbol en barra lateral, diagrama ER en vivo, tarjetas al pasar el cursor, 18 reglas de lint con QuickFixes |
| Usuario de terminal / CI | pip install django-orm-lens | 17 subcomandos, SARIF + anotaciones de PR, hooks de pre-commit, una GitHub Action |
| Usuario de agente de IA — Cursor / Claude Code / Aider / Zed / Continue | pip install "django-orm-lens[mcp]" | 13 herramientas MCP de solo lectura que responden preguntas de esquema desde la fuente de verdad |
La configuración de MCP es un bloque JSON — ver Integraciones. Apunta DJANGO_ORM_LENS_ROOT a la ruta absoluta de tu proyecto Django.
🆓 Capacidades de nivel de pago, gratis y MIT
La revisión de esquemas es una categoría de pago en casi todas partes. Un bot que revisa cada pull request, análisis que sigue un queryset más allá de la función donde se creó, una comprobación que detecta deriva de esquema, consejos de índices basados en estadísticas reales de tablas — todo eso normalmente está detrás de una suscripción por asiento o por base de datos.
Todo está aquí, con licencia MIT, sin límite de nivel, sin conteo de asientos, sin cuenta y sin telemetría:
| Capacidad normalmente vendida como nivel de pago | Aquí |
|---|---|
| Bot de revisión de PR para cambios de esquema — publica una vez, luego actualiza en el lugar | blast-radius + la Action |
| Análisis que sigue un queryset a través de funciones | nplusone |
| Detección de deriva de esquema | drift |
| Propuestas de índices desde el uso observado de QuerySet | suggest-indexes |
| Riesgo de migración ponderado contra tamaños reales de tablas | blast-radius --stats |
| Radio de impacto de una migración destructiva | blast-radius |
| Impacto entre capas de eliminar un campo | impact |
No hay nivel Pro, y no está planeado. Si la herramienta te ahorra una tarde, una estrella es todo lo que pedimos.
📊 Tracción
Si la herramienta te ahorra un
grepla próxima vez que toques un proyecto Django desconocido — una estrella ayuda a otros a encontrarla.
📈 Crecimiento de estrellas
⚡ Instalación
VS Code / Cursor / Windsurf (VS Code Marketplace):
code --install-extension frowningdev.django-orm-lens
VSCodium / code-server / Gitpod / cualquier fork de Code OSS (Open VSX):
codium --install-extension frowningdev.django-orm-lens
O busca Django ORM Lens en la vista de Extensiones — mismo editor frowningdev en ambos registros.
Agentes de terminal y de codificación con IA:
pip install django-orm-lens # CLI only
pip install "django-orm-lens[mcp]" # + MCP server for AI agents
Requiere Python 3.9+. Cero dependencias de ejecución para la CLI.
Docker (v0.6+):
docker run --rm -v "$PWD:/workspace" ghcr.io/frowningdev/django-orm-lens scan --path .
Multi-arquitectura (amd64 + arm64). No se requiere Python en el host. Ideal para CI y auditorías puntuales.
🎯 El problema
Funciona sin conexión. Funciona con un venv roto. Funciona en el portátil de otra persona. Funciona en CI.
Abres un proyecto Django. Tiene 20 apps. Necesitas responder una pregunta simple:
"¿Qué app es dueña del modelo
Order, y cómo está conectado aUser?"
Hoy, eso significa: Ctrl+P, "models", desplazarte por 30 resultados, abrir cinco archivos, Ctrl+F para class Order, leer 400 líneas de cadenas ForeignKey('otherapp.Something'), intentar recordar lo que aprendiste hace dos archivos.
Medio día perdido. Cada vez. En cada proyecto.
✨ Con Django ORM Lens
📚 Un árbol de todoCada app → cada modelo → cada campo → cada opción Los iconos distinguen |
🕸️ Un diagrama ER en vivoUn comando abre un diagrama de entidad-relación Mermaid de todo tu esquema. Observa cómo se redibuja mientras editas. Exporta a SVG.
|
🔎 Pasa el cursor para ver relacionesPasa el cursor sobre |
🧭 Ir a la definiciónHaz clic en cualquier campo del árbol → el cursor aterriza en la línea exacta. Filtra el árbol por nombre de app o modelo. Los paquetes divididos |
⚡ Cero configuraciónSin |
🎨 Interfaz nativa de VS CodeTema oscuro. Tema claro. Tu tema. Sigue tu tema de iconos, tu fuente, tus atajos de teclado. Nada llamativo, nada de marca. |
🚀 Funciones avanzadas
💥 Radio de impactoLa pregunta en tiempo de revisión que un cambio de esquema realmente plantea: ¿qué afecta esto? Cada operación de migración destructiva se convierte en un objetivo que lleva sus riesgos, cada lugar en el código que aún lo lee y — para operaciones de modelo completo — el efecto en cascada.
|
🧭 Deriva de esquema
La propia comprobación de Django necesita un módulo de configuración funcional, un registro de apps importable y todas las dependencias instaladas — no disponible en un clon en frío o un venv roto, que es exactamente cuando la respuesta es más barata de actuar. Solo la dirección peligrosa falla la compilación: un campo declarado pero nunca migrado significa que la columna no existirá, y la primera consulta que lo toca da error. |
🎯 Diagnósticos en línea y QuickFixes (18 reglas)Análisis estático sobre archivos Suprime en línea con |
🧪 Generador de factoriesClic derecho en cualquier modelo → También disponible como CodeLens sobre cada clase de modelo. |
🕰 Diff de esquema con viaje en el tiempoElige un Los renombres son eventos de primera clase, nunca |
🔎 Análisis de impacto"¿Qué se rompe si elimino este campo?" — clic derecho en un campo o modelo → escaneo de todo el espacio de trabajo agrupado por capa de Django (models, serializers, forms, admin, views, urls, templates, tests, migrations). Los hallazgos llevan una etiqueta de confianza Cierto / Probable / Posible. Maneja referencias de cadena ORM ( |
⚡ Constructor de consultas interactivoClic derecho en un campo o modelo → elige una plantilla → snippet insertado en el cursor (con tab-stops) o en un buffer nuevo sin título.
|
🎨 Renovación de la barra lateral
Insignias |
📸 Cómo se ve
Muestra en vivo — salida real de django-orm-lens er, renderizada por GitHub aquí mismo:
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]"
También incluido en la extensión:
- 🕸️ Diagrama ER en vivo — flechas de cardinalidad Mermaid, etiquetas de bordes (
CASCADE,through Model,as related_name), consciente del tema, exportación SVG con un clic - 🔎 Tarjetas flotantes — sobre cualquier
ForeignKey('app.Model')oManyToManyField(...), con un enlace de salto de un clic - 🧭 CodeLens — encima de cada línea de
class Model: recuento de campos, recuento de relaciones y una acción Abrir diagrama ER - 🎨 Temas con nombre —
auto/default/dark/forest/neutralpara la vista web del diagrama
🤖 Para terminales y agentes de IA de codificación
El mismo analizador que impulsa la extensión de VS Code se distribuye como un paquete Python independiente, con un servidor MCP (Model Context Protocol) opcional para que cualquier agente de IA compatible con MCP pueda navegar por tu esquema de Django sin importar Django ni iniciar tu aplicación.
CLI
django-orm-lens scan -f json # every app, every model, every field
django-orm-lens describe blog.Post # one model in Markdown
django-orm-lens list | fzf # flat app.Model — pipes anywhere
django-orm-lens er > schema.mmd # ER diagram — Mermaid (default)
django-orm-lens er -f dbml > schema.dbml # …or DBML: paste into dbdiagram.io
django-orm-lens er -f d2 > schema.d2 # …or D2 / plantuml / dot
django-orm-lens diff before.json after.json # what a PR changes structurally
django-orm-lens nplusone --format github # N+1 findings as PR annotations
django-orm-lens migration-risk -f sarif # SARIF for GitHub Code Scanning
django-orm-lens suggest-indexes blog.Post # Meta.indexes proposals from usage
django-orm-lens signals # sender→signal→handler graph
django-orm-lens migration-deps blog -f mermaid # per-app migration DAG
django-orm-lens cascade blog.Author # what one delete() takes down
django-orm-lens impact author # what still references a field
django-orm-lens blast-radius -f markdown # risks + who still reads them
django-orm-lens drift # migrations vs models, no boot
django-orm-lens stats-sql # read-only SQL for --stats
impact,blast-radius,driftystats-sqlse incluyen en py-1.7.0 y versiones posteriores.
Cada comando acepta --path <dir> y --exclude <glob>. nplusone / migration-risk / diff salen con código 1 si hay hallazgos: úsalos en CI para bloquear PRs por regresiones.
Servidor MCP
Regístralo una vez con tu agente y expone trece herramientas de solo lectura:
| Herramienta | Propósito |
|---|---|
list_apps | Cada aplicación de Django en el espacio de trabajo con recuentos de modelos |
list_models | Lista plana de app.Model, filtro opcional por aplicación |
describe_model | Detalle completo de campos / relaciones / Meta para un modelo |
find_relations | Relaciones entrantes y salientes para un modelo |
cascade_preview | Radio de impacto de un delete(), agrupado por on_delete |
er_diagram | Diagrama ER — mermaid / dbml / d2 / plantuml / dot |
describe_migration_dependency | DAG de migraciones por aplicación: raíces, hojas, dependencias entre aplicaciones |
suggest_indexes | Propuestas de Meta.indexes a partir del uso observado de QuerySet |
signal_graph | Grafo emisor→señal→manejador desde decoradores @receiver |
blast_radius | Qué afecta una migración destructiva: sus riesgos, el código que aún la lee, el impacto en cascada |
drift | makemigrations --check sin iniciar Django — migraciones comparadas contra models.py |
impact | Cada referencia a un campo o nombre de modelo, agrupada por capa de Django |
nplusone_scan | Hallazgos estáticos de N+1 para todo el espacio de trabajo |
# Start it directly
django-orm-lens-mcp
# Or via the CLI subcommand
django-orm-lens mcp
Resolución del espacio de trabajo (py-1.3.0+). Cada herramienta acepta un argumento opcional
workspace_root en la llamada. Prioridad de resolución: argumento explícito →
$DJANGO_ORM_LENS_ROOT → directorio de trabajo actual. Rutas inválidas o no-Django
devuelven un sobre estructurado
({"error": "WORKSPACE_NOT_DJANGO", "hint": "…"}) en lugar de resultados vacíos,
para que el agente pueda autocorregirse. Sandbox opcional mediante
DJANGO_ORM_LENS_ALLOWED_ROOTS (separado por ; en Windows, : en otros sistemas).
🛡️ Protege tu CI
Las regresiones de esquema son más baratas de detectar en el momento en que entran a un PR. Cuatro formas sin configuración para bloquearlas:
Bot de PR de radio de impacto — toda la revisión de esquema en un solo comentario, actualizado en el lugar en cada push en lugar de un comentario nuevo cada vez:
name: Schema review
on: pull_request
permissions:
contents: read
pull-requests: write # only for `comment: true`
jobs:
blast-radius:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: FROWNINGdev/django-orm-lens@action-v1
with:
command: blast-radius
only-changed: true # scope to migrations this PR touches
comment: true # post once, then update in place
github-token: ${{ github.token }}
El comentario se publica antes de que falle el trabajo, así que un PR bloqueado aún explica por qué. only-changed lee la lista de archivos del PR desde la API en lugar de git diff, porque actions/checkout por defecto es fetch-depth: 1 y el commit base no está en el historial local. En eventos de push ambas banderas se omiten con un aviso en lugar de fallar, así que un solo flujo de trabajo cubre ambos disparadores.
La acción se instala desde PyPI, así que
blast-radiusydriftnecesitan py-1.7.0 o posterior — fíjala conversion: 1.7.0si tu flujo de trabajo no debe desviarse. Para ejecutar una versión no publicada, agregainstall: falsee instala la fuente tú mismo; el flujo de trabajo de este repositorio hace exactamente eso, y es lo que verifica la acción en cada PR.
pre-commit — dos hooks, nada que instalar localmente:
# .pre-commit-config.yaml
repos:
- repo: https://github.com/FROWNINGdev/django-orm-lens
rev: py-v1.13.0
hooks:
- id: django-orm-lens-nplusone
- id: django-orm-lens-migration-risk
GitHub Action — los hallazgos aparecen como anotaciones de PR con cero permisos adicionales:
- uses: FROWNINGdev/django-orm-lens@action-v1
with:
command: migration-risk # or: nplusone
format: github # ::error / ::warning annotations on the diff
SARIF → Code Scanning — los hallazgos llegan a la pestaña de Seguridad del repositorio:
- run: |
pip install django-orm-lens
django-orm-lens migration-risk --format sarif --exit-zero > lens.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: lens.sarif
Los códigos de salida son nativos de CI: diff y nplusone salen con 1 si hay hallazgos, migration-risk y blast-radius salen con 1 en hallazgos críticos, drift sale con 1 cuando un campo se declara pero nunca se migra. Agrega --exit-zero para el modo solo informe.
🔌 Integraciones
| Cliente | Cómo habilitarlo | Estado |
|---|---|---|
| VS Code | code --install-extension frowningdev.django-orm-lens | ✅ |
| Cursor | mismo VSIX + entrada MCP opcional en ~/.cursor/mcp.json | ✅ |
| Windsurf / VSCodium / cualquier fork de Code | instala el VSIX desde el Marketplace o GitHub Releases | ✅ |
| Aider | agrega django-orm-lens-mcp a tu mcp.json | ✅ (vía MCP) |
| Continue.dev | registra el servidor MCP en ~/.continue/config.json | ✅ (vía MCP) |
| Zed | registra el servidor MCP en la configuración de Zed | ✅ (vía MCP) |
| Cualquier cliente compatible con MCP | apunta command a django-orm-lens-mcp, establece DJANGO_ORM_LENS_ROOT | ✅ |
| pre-commit | repo: https://github.com/FROWNINGdev/django-orm-lens + dos IDs de hook | ✅ |
| GitHub Actions | uses: FROWNINGdev/django-orm-lens@action-v1 — anotaciones o SARIF | ✅ |
| Descubrible vía MCP Registry | directorio oficial de servidores Model Context Protocol | ✅ |
| Terminal simple / CI | pip install django-orm-lens && django-orm-lens scan | ✅ |
Ejemplo: Cursor / cualquier cliente MCP
{
"mcpServers": {
"django-orm-lens": {
"command": "django-orm-lens-mcp",
"env": { "DJANGO_ORM_LENS_ROOT": "/abs/path/to/your/project" }
}
}
}
⚡ Rendimiento
La suite de regresión analiza los grafos de modelos incluidos de Zulip, Saleor, Wagtail, django CMS y Mezzanine — 59 modelos en 13,478 líneas de models.py real — en aproximadamente 20 ms de extremo a extremo en una laptop (21 ms mejor de 3 en el corpus de fixtures dorados del repositorio; una guardia de <2 s se ejecuta en CI en cada celda de la matriz).
Reprodúcelo tú mismo:
git clone https://github.com/FROWNINGdev/django-orm-lens && cd django-orm-lens/cli
pip install -e . && python -m pytest tests/test_golden_fixtures.py tests/test_golden_snapshots.py -q
🎯 Para quién es esto
- Desarrolladores de Django que se unen a un código con 10+ aplicaciones y se pierden en el desorden de
models.py. - Ingenieros freelance / por contrato que necesitan comprender un proyecto Django desconocido en la primera hora, no en la primera semana.
- Equipos que incorporan nuevos empleados que quieren una vista de esquema de un vistazo sin levantar infraestructura de documentación.
- Usuarios avanzados de agentes de IA (Cursor / Aider / Zed / Continue / cualquier cliente compatible con MCP) que necesitan que el agente responda preguntas de esquema con precisión — sin darle credenciales de base de datos ni iniciar Django.
- Pipelines de CI que verifican la forma del esquema (por ejemplo, "¿rompimos accidentalmente un
related_name?") sin importar el proyecto. - Desarrolladores independientes en solitario con un venv roto o en la laptop de otra persona — sin
runserver, sinmanage.py migrate, aún funciona.
🗺️ Posición en el mercado
Django ORM Lens se encuentra en la intersección de herramientas de editor y herramientas de agentes de IA — un espacio que ningún paquete existente cubre:
| Segmento | Opción existente | Qué te cuesta |
|---|---|---|
| Iniciar y graficar | django-extensions graph_models | Requiere Graphviz + configuración de Django + una URL de base de datos funcional |
| Visor basado en web | django-schema-graph | Requiere un servidor Django en ejecución; aloja una cosa más que puede fallar |
| Panel de administración | Django Admin | Requiere runserver + autenticación + base de datos — excelente para datos, no para arquitectura |
| Plugin de editor | Estructura de Django en PyCharm | Bloqueado a PyCharm; sin CLI, sin historia de agentes de IA |
| Servidor MCP | (ninguno hasta ahora) | Los agentes de IA adivinan tu esquema desde el código fuente, de manera imperfecta |
Django ORM Lens es la única herramienta que ofrece tres superficies desde un solo analizador: una extensión de VS Code (cualquier fork de Code), una CLI sin dependencias (terminales + CI) y un servidor MCP (agentes de IA). Todo estático. Todo gratuito. Todo MIT.
🤔 ¿En qué se diferencia?
| Django ORM Lens | django-extensions graph_models | django-schema-graph | Django Admin | Estructura de Django en PyCharm | |
|---|---|---|---|---|---|
| Funciona sin un proyecto Django iniciable | ✅ | ❌ | ❌ | ❌ | ⚠️ |
| Sin instalación (sin graphviz, sin servidor) | ✅ | ❌ | ❌ | ❌ | ❌ (necesita PyCharm) |
| Funciona en VS Code / Cursor / cualquier fork de Code | ✅ | ❌ | ❌ | ❌ | ❌ |
| Árbol lateral dentro del editor | ✅ | ❌ | ❌ | ❌ | ✅ |
| Diagrama ER en vivo | ✅ | ✅ | ✅ | ❌ | ❌ |
Tarjetas flotantes en ForeignKey | ✅ | ❌ | ❌ | ❌ | ⚠️ |
| CodeLens en clases de modelo | ✅ | ❌ | ❌ | ❌ | ❌ |
Soporte de paquete models/ dividido | ✅ | ⚠️ | ⚠️ | ✅ | ✅ |
| CLI para terminal / CI | ✅ | ⚠️ | ❌ | ❌ | ❌ |
| Servidor MCP para agentes de IA | ✅ | ❌ | ❌ | ❌ | ❌ |
| Descubrible en el MCP Registry | ✅ | ❌ | ❌ | ❌ | ❌ |
| Gratuito y de código abierto (MIT) | ✅ | ✅ | ✅ | ✅ | ❌ (IDE de pago) |
| Soporte de versiones de Django | 4.0 – 5.2 | última | 3.2 – 4.1 (obsoleto desde 2023) | última | última |
django-schema-graphno se ha actualizado desde 2023-05 y no prueba Django 5.x.
Cuando quieres algo más
Límites honestos: perfilado de una solicitud en vivo → django-debug-toolbar. Perfilado histórico de solicitudes → django-silk. Aserciones de recuento de consultas dentro de una suite de pruebas → django-perf-rec. APM de producción en tráfico real → Scout / Sentry. Django ORM Lens deliberadamente se mantiene estático — es la capa que funciona antes de que la aplicación pueda iniciar, y la única que tu CI y tu agente de IA pueden usar en cualquier checkout.
⚙️ Configuración
Los valores predeterminados son opinados y sensatos. Si necesitas ajustar:
// .vscode/settings.json
{
"djangoOrmLens.excludeGlobs": [
"**/migrations/**",
"**/node_modules/**",
"**/venv/**",
"**/.venv/**",
"**/env/**"
],
"djangoOrmLens.autoRefresh": true
}
| Configuración | Tipo | Predeterminado | Qué hace |
|---|---|---|---|
djangoOrmLens.excludeGlobs | string[] | Ver arriba | Patrones glob para omitir al escanear |
djangoOrmLens.autoRefresh | boolean | true | Reescaneo en cambios de models.py |
djangoOrmLens.codeFixes.enabled | boolean | true | Interruptor principal para los diagnósticos DOL### + QuickFixes |
djangoOrmLens.rules | object | {} | Severidad por regla: { "DOL007": "off", "DOL013": "error" } |
djangoOrmLens.rulesSelect | string[] | [] | Selección estilo Ruff. ["DOL0"] ejecuta solo reglas de queryset+modelo |
djangoOrmLens.rulesIgnore | string[] | [] | Ignorar estilo Ruff. ["DOL03"] silencia reglas de formularios/vistas |
🔬 Catálogo de reglas
Dieciocho verificaciones del lado del editor (DOL001–DOL041) con códigos estilo Ruff, severidad por regla y aplicabilidad estilo Clippy — más dieciséis reglas de riesgo de migración del lado de CLI y el analizador estático de N+1. Cada regla ahora tiene su propia página de documentación.
| Categoría | Reglas | Ejemplos |
|---|---|---|
| Queryset | DOL001–DOL007 | .count() > 0 → .exists(), acceso a FK en bucles (N+1) |
| Definición de modelo | DOL011–DOL015 | ForeignKey sin on_delete, null=True en campos de cadena |
| Datetime | DOL021–DOL022 | datetime.now() → timezone.now() |
| Formularios / vistas | DOL031–DOL032 | locals() en render(), Meta.fields = '__all__' |
| SQL crudo | DOL041 | SET enable_hashjoin = off, plan_cache_mode, jit anulaciones en código de aplicación |
| Riesgos de migración | 16 reglas | NOT NULL agregado sin valor predeterminado, construcciones de índice con bloqueo de tabla, migraciones de datos irreversibles |
| N+1 estático | 1 analizador | Acceso a FK/M2M en bucles sin select_related / prefetch_related |
→ Referencia completa de reglas — cada código con ejemplos malos/buenos, comportamiento de QuickFix y sintaxis de supresión.
Suprimir en línea
# django-orm-lens-disable-next-line DOL007
for user in User.objects.all():
print(user.profile) # not flagged
qs.count() > 0 # django-orm-lens-disable-line DOL001
# django-orm-lens-disable DOL011 ← on its own line, kills DOL011 for the rest of the file
La aplicabilidad sigue el Clippy de Rust: las correcciones seguras se pueden aplicar automáticamente ("Corregir todo"), las correcciones de sugerencia se ofrecen como QuickFix pero se revisan, los hallazgos inseguros nunca se aplican automáticamente. Las correcciones están separadas de los analizadores (estilo Roslyn), por lo que una regla puede crecer con múltiples correctores con el tiempo sin tocar la lógica de detección.
🧭 Comandos
Abre la paleta de comandos (Ctrl+Shift+P / Cmd+Shift+P) y escribe "Django ORM Lens":
| Comando | Qué hace |
|---|---|
Django ORM Lens: Refresh | Forzar un nuevo escaneo del espacio de trabajo |
Django ORM Lens: Show ER Diagram | Abrir el diagrama ER de Mermaid en paralelo |
Django ORM Lens: Filter Models | Filtrar el árbol por nombre de app / modelo / campo |
Django ORM Lens: Clear Filter | Restaurar el árbol completo |
Django ORM Lens: Jump to Model | Programático — se activa con clics en el árbol y tarjetas flotantes |
Django ORM Lens: Find Reverse References | Clic derecho en un modelo — QuickPick de cada FK que apunta a él |
Django ORM Lens: Generate factory_boy Factory | Clic derecho en un modelo o usar CodeLens — generar un DjangoModelFactory |
Django ORM Lens: Schema Diff (Time-Travel) | Elegir dos commits — obtener un diff tipado como buffer de markdown |
Django ORM Lens: Find Impact (What Uses This?) | Clic derecho en un campo o modelo — escaneo de referencias en todo el espacio de trabajo |
Django ORM Lens: Build Query (Insert Snippet) | Clic derecho en un campo o modelo — elegir una plantilla ORM |
🗺️ Hoja de ruta
Publicado
- Árbol lateral agrupado por app
- Diagrama ER de Mermaid en vivo
- Tarjetas flotantes sobre
ForeignKey('app.Model') - Filtrar árbol por nombre
- Soporte de paquetes
models/divididos - Exportar diagrama ER como SVG
- CLI de Python + servidor MCP para terminales y agentes de IA
- Vista de bienvenida para espacios de trabajo vacíos
- Ir a definición seguro para rutas y markdown flotante saneado
- v0.3.0 — CodeLens sobre cada clase de modelo (
N fields · N relations · Open ER diagram) - v0.3.0 — Etiquetas de aristas en el diagrama (
CASCADE,SET_NULL,PROTECT,related_name) - v0.3.0 — Temas de color con nombre (
auto/default/dark/forest/neutral) - v0.3.1 —
through_modelen aristas M2M (contribuido por @kingrubic) - v0.3.1 — Listado en el Registro oficial de MCP + Glama.ai
- v0.6.0 — CLI
nplusone— detector estático de N+1 (acceso a FK/M2M dentro de bucles sinselect_related/prefetch_related) - v0.6.0 — CLI
migration-risk— marca operaciones riesgosas enmigrations/*.py(15 reglas hoy) - v0.6.0 — CLI
diff— comparar dos volcados JSON de esquema para revisión de PR - v0.6.0 — Minimapa del diagrama ER colorea nodos por app de Django
- v0.6.0 — Traducciones del README: 🇷🇺 Ruso, 🇪🇸 Español, 🇨🇳 Chino
- v0.6.0 — Imagen Docker en GHCR:
docker run ghcr.io/frowningdev/django-orm-lens - v0.7.0 —
settings.AUTH_USER_MODELse resuelve en todas partes: relaciones inversas n+1, remitentes de señales, Mermaid ER, webview de VS Code, panel de relaciones entrantes, ER de React - v0.7.0 — Analizador de campos basado en AST:
ForeignKey(on_delete=CASCADE, to='User')se resuelve independientemente del orden de kwargs (paridad Python + TS) - v0.7.0 — Helpers compartidos públicos:
find_user_model,resolve_related_tail,find_model,iter_workspace_py_files(Python) +findUserModel,resolveRelatedTail(TS) - v0.7.0 —
--verboseya no recorre el árbol dos veces;WorkspaceIndex.scanned_fileslleva el conteo - v0.7.3 — Anotaciones de tipo PEP-526 en campos (
jti: CharField[str] = models.CharField(...)) ahora se analizan — reportado por @jsabater (#25) con una reproducción limpia de Django Ninja 1.6 - v0.7.4 — Cabeceras de clase genéricas PEP-695 (Python 3.12+):
class Container[T](models.Model):ahora se analiza - v0.7.5 — Módulo de modelos con alias (
from django.db import models as m) y paquetes de campos de terceros (jsonfield.JSONField) ahora se detectan - v0.7.6 — Cuerpos de modelo con sangría de tabulaciones ahora se analizan (los editores que usan tabulaciones por defecto ya no muestran modelos vacíos)
- v0.8.0 — QuickFixes en línea: 16 reglas (
DOL001..DOL032) con severidad por regla + select/ignore estilo Ruff +# django-orm-lens-disable-next-lineen línea - v0.8.0 — Generador de fábricas:
factory_boya partir de cualquier modelo con proveedores de Faker según el tipo de campo - v0.8.0 — Diff de esquema con viaje en el tiempo: elegir dos commits → diff de markdown tipado con detección de renombrados de primera clase
- v0.8.0 — Análisis de impacto: escaneo de referencias de campos en todo el espacio de trabajo en cada capa de Django con etiquetas de confianza Cierto/Probable/Posible
- v0.8.0 — Constructor de consultas interactivo: clic derecho → plantilla → fragmento insertado en el cursor, consciente de la gramática (FK obtiene
.select_related,related_namerespetado) - v0.8.0 — Renovación de UX del panel lateral:
TreeItem.idestable, tooltips deMarkdownStringcon enlaces profundos decommand:, insignias deFileDecorationProvider,TreeView.badgeen la barra de actividad, tres estados deviewsWelcomecon compuerta
v1.5.0 — la ola de "un núcleo, tres superficies"
- Formatos de CI: SARIF 2.1.0 + anotaciones de PR de
--format githubparanplusoneymigration-risk - Cuatro analizadores promovidos de solo MCP a la CLI:
suggest-indexes,signals,migration-deps,cascade -
er --format dbml | d2 | plantuml | dot— exportaciones de diagramas estándar de la comunidad (dbdiagram.io, D2, PlantUML, Graphviz —dotcontribuido por @JJordan0C) - Tres nuevas reglas de riesgo de migración:
runpython_no_reverse,alter_unique_together_lock,alter_index_together_deprecated— 15 en total - Hooks de pre-commit (
django-orm-lens-nplusone,django-orm-lens-migration-risk) + Acción de GitHub compuesta -
docs/rules/— una página de documentación para cada regla (19 páginas) - Suite de regresión de instantáneas doradas sobre 59 modelos reales (Zulip / Saleor / Wagtail / django CMS / Mezzanine); ruff + mypy ahora controlan el CI
- Grafo de dependencias de migraciones —
migration-deps(texto / json / mermaid)
py-1.7 → 1.8 — la ola de inteligencia de esquema
-
blast-radius— riesgos de migración combinados con lo que aún lee el esquema que tocan, como bot de PR (comment: true, fijo,only-changed) -
drift—makemigrations --checksin iniciar Django -
impact <name>— lo que aún referencia un modelo o campo, agrupado por capa de Django -
blast-radius --stats+stats-sql— conteos de filas de producción opcionales desde SQL de solo lectura que ejecutas tú mismo (la herramienta nunca tiene credenciales de base de datos) -
nplusonese resuelve entre funciones — un queryset devuelto por un helper se sigue hasta el bucle que lo consume -
blast_radius,driftyimpactexpuestos como herramientas MCP — trece herramientas para agentes de IA -
driftdocumenta sus marcas de!!/~en el informe y en--help— reportado por @sevdog (#57) -
driftsigue la herencia de bases abstractas — los campos de una base abstracta cuentan como propios del hijo concreto, como los trata Django — reportado por @sevdog (#58) -
suggest-indexreconoce los índices que Django ya creó — clave primaria (pkyidson una sola búsqueda),db_index,unique, claves foráneas,unique_together,UniqueConstraint— reportado por @sevdog (#60), misma causa encontrada independientemente por @RinZ27 (#61) - Una sexta fixture dorada — Read the Docs se une a Zulip, Saleor, Wagtail, django-CMS y Mezzanine, poniendo al analizador bajo 75 modelos y 538 campos de Django real — contribuido por @JJordan0C (#62, cerrando #51)
-
TaggableManagerde django-taggit se lee como el M2M que es — a través detaggit.TaggedItemataggit.Tag,through=respetado, tanto en el analizador de Python como en el de TypeScript — contribuido por @Guflly (#63, cerrando #50) -
DOL021indica el valor predeterminado deUSE_TZcorrectamente —Falsehasta Django 4.2,Truedesde 5.0, con elUSE_TZ = Truede la plantillastartprojectdesde 4.0 señalado como la cosa separada que es — y ya no afirma quetimezone.now()siempre es consciente de UTC — encontrado por @Justine0211 mientras traducía la página (#52) - La fixture
parity_input.pylleva la importación demodelsque unmodels.pyreal tendría — contribuido por @RinZ27 (#64)
py-1.9 → 1.12 — la ola de checkout real
Encontrado ejecutando la CLI sobre checkouts reales de django-oscar, django-guardian, django-allauth y django-cms en lugar de sobre fixtures. Cada uno de estos era invisible para una suite de pruebas verde, y dos de ellos hicieron que la herramienta respondiera con confianza algo falso.
- Los modelos declarados dentro de un bloque a nivel de módulo se analizan — el modismo de modelo intercambiable (
if not is_model_registered(...):y luego unclassindentado) que usa todo framework Django conectable, contra el descubrimiento de clases anclado en^class. django-oscar pasó de 12 modelos, cada uno de su propio directoriotests/, a 82. Las seis instantáneas doradas permanecieron byte-idénticas: una clase en columna 0 se analiza exactamente como antes -
abstract_models.pyse lee junto conmodels.py— los frameworks conectables mantienen la base abstracta allí y dejan quemodels.pycontenga solo la subclase concreta, así que 72 de los 83 modelos de django-oscar reportaban cero campos entre ellos. Ahora 8, y esos 8 son correctos: subclasifican modelos concretos, donde la herencia de múltiples tablas deja las columnas en la tabla del padre -
driftya no falla una compilación por dos directorios de app que comparten nombre — el estado de migración reproducido se fusiona por nombre de app, coincidiendo con cómo ya se clavea el lado declarado. En un checkout real de django-guardian el conteo de bloqueo va de 1 → 0 y la fila duplicada contradictoria desaparece, mientras que un campo genuinamente sin migrar aún bloquea - Los modelos de django-mptt ya no son invisibles —
MPTTModeles una base reconocida, yTreeForeignKey/TreeOneToOneField/TreeManyToManyFieldse reportan como los campos de Django que subclasifican, así queTreeForeignKey('self', ...)dibuja exactamente la auto-arista que unForeignKey('self', ...)simple hace. No se agrega dependencia dedjango-mptt— el analizador sigue funcionando contra un venv roto. Elproduct.Categoryde Saleor y su arista dechildrenahora aparecen en la instantánea dorada: 76 líneas agregadas, ninguna eliminada (cerrando #49) - El servidor MCP reporta su propia versión —
FastMCPno reenvía ninguna, así que el SDK caía enimportlib.metadata.version("mcp")y cada respuesta deinitializenombraba el número de versión del proyecto equivocado al cliente
v0.9 → v0.12.1 — la extensión se pone al día
- v0.9.0 — Seguimiento parcial de
UniqueConstrainten Time-Travel Schema Diff:add/drop/change/renamecomo eventos tipados, confromConditionllevando el predicado previo al cambio para que un comentario de revisión pueda mostrarQ(is_primary=True) → Q(is_primary=True, deleted=False), y un renombrado que ya no aparece como un paradd + dropcon pérdida de información. Múltiples restricciones sin nombre en un mismo modelo se asignan a#anon-<index>en lugar de colapsar en un solo evento. Motivado por django-extensions #1813, dondesqldiffelimina el predicadocondition=y los revisores de migraciones nunca ven qué cambió - v0.10.0 — La detección de capas del análisis de impacto se ejecuta sobre la ruta relativa al workspace. Antes coincidía con
/tests/y/views.pyen cualquier parte de la ruta absoluta de un archivo, por lo que un proyecto clonado en cualquier directorio llamadotests— o un monorepo conservices/tests/por encima — reportaba cada archivo como esa capa,views.pycomo prueba,admin.pycomo prueba. También: los mensajes del webview se validan por origen en lugar de por fuente, y se detectan migraciones hoja en conflicto — dos migraciones que reclaman el mismo padre, algo que Django solo reporta en tiempo demigrate - v0.10.1 — La ficha de Marketplace menciona análisis de impacto, radio de explosión y deriva de esquema, y dice claramente que la herramienta es gratuita y MIT sin nivel Pro. La página de la tienda aún describía la extensión como un panel lateral y un diagrama ER — lo que era dos versiones antes — así que nadie que buscara esas funciones la encontraba. Los metadatos solo surten efecto al publicar, por eso necesitaba su propio lanzamiento
- v0.11.0 — La mitad TypeScript del soporte de django-mptt, publicada como lanzamiento propio en lugar de integrarse en uno posterior: entre py-1.12.0 y esta compilación, la CLI y la extensión discrepaban sobre qué contiene un esquema django-mptt, que es exactamente el fallo que el fixture dorado compartido existe para prevenir
- v0.12.0 — La extensión pide una estrella de GitHub en la tercera apertura iniciada por el usuario del diagrama ER. No al instalar: un aviso que llega antes de que la herramienta haya hecho nada se descarta por reflejo, y ese descarte es permanente en la mente del usuario. Las actualizaciones del panel lateral que re-renderizan un panel ya abierto no cuentan — no son una petición del usuario. "Más tarde" y "No volver a preguntar" se almacenan como estados separados, de modo que un aplazamiento rearma la pregunta exactamente una vez, doce aperturas después; dos avisos es el máximo de por vida. La política es una función pura cubierta por seis pruebas que no necesitan host de VS Code
- v0.12.1 — Exportar como SVG escribía un archivo ilegible.
toSvgdevuelve marcado con codificación porcentual dondetoPngdevuelve base64; la ruta de guardado asumía base64 para cualquier cosa que empezara condata:, y decodificar base64 de texto con codificación porcentual no falla — el decodificador descarta silenciosamente cada carácter fuera de su alfabeto y devuelve bytes. Un documento<svg>de 48 caracteres llegaba al disco con el nombre correcto, un tamaño plausible y ningún contenido válido en ninguna parte. La codificación de transferencia ahora se lee del encabezado de la URL de datos en lugar de adivinarse por el prefijo
Siguiente
- v0.13.0 — Autocompletado de campos dentro de
.filter()/.exclude()/.get()(#3) - v0.10.0 — Casillas de alternancia de app / modelo: desmarca una app o modelo en el panel lateral para eliminarlo del diagrama ER
- Motor de reglas DOL portado a la CLI de Python — un catálogo de reglas, tres superficies
Más adelante
- Soporte de campos de terceros —
django-model-utils(django-taggitincluido en py-1.11.0,django-mptten py-1.12.0 / v0.11.0) - Plugin para JetBrains / PyCharm (si hay demanda)
Vota con 👍 en el issue correspondiente.
❓ Preguntas frecuentes
¿Envías algo de mi código a un servidor?
No. Cada byte permanece en tu máquina. El analizador es TypeScript puro (extensión) o Python puro (CLI). Sin llamadas a LLM, sin telemetría, sin analíticas, sin informes de errores. El renderizador de Mermaid se ejecuta dentro del sandbox del webview de VS Code.
¿Funciona con Poetry / uv / conda / sin venv en absoluto?
Sí. La extensión lee el código fuente de Python directamente — no importa Django y no le importa qué gestor de paquetes uses. La CLI requiere Python 3.9+, pero eso es todo.
Mis modelos están divididos en varios archivos dentro de un paquete models/. ¿Eso funciona?
Sí, desde v0.2.0. Tanto la extensión como la CLI recorren
models/*.py junto con el clásico models.py.
¿Puedo usarlo con serializers de DRF, Wagtail, Oscar o modelos base de terceros?
Se detecta cualquier clase que parezca un modelo de Django: subclases de
models.Model, bases abstractas que empiecen con Abstract, mixins comunes que terminen en Mixin, y nombres base conocidos como TimeStampedModel o PolymorphicModel. Las clases que no son modelos (ModelAdmin, ModelSerializer, Form, View, Manager, …) se filtran.
¿Qué agentes de IA pueden usar el servidor MCP?
Cualquier cliente compatible con MCP — Cursor, Aider, Continue.dev, Zed y cualquier otra herramienta que hable el protocolo. Solo apunta
command al binario instalado django-orm-lens-mcp. Consulta la sección Integrations.
¿Cómo bloqueo regresiones de esquema en CI?
Tres formas, todas de configuración cero: los dos pre-commit hooks, la acción compuesta de GitHub (
uses: FROWNINGdev/django-orm-lens@action-v1 con format: github para anotaciones en PR), o --format sarif canalizado a github/codeql-action/upload-sarif para la pestaña de Seguridad. diff / nplusone salen con código 1 si hay hallazgos, migration-risk sale con código 1 si hay hallazgos críticos.
¿Hay una versión para JetBrains / PyCharm?
Todavía no. La ventana de herramientas Django Structure de PyCharm ya es buena, así que el valor añadido es menor. Si suficiente gente lo pide, merece la pena hacerlo.
🆘 Soporte
- 🐛 Informes de errores — GitHub Issues (incluye un fragmento mínimo de
models.py) - 💡 Solicitudes de funciones / ideas — GitHub Discussions
- 📝 Reseñas en Marketplace — valora la extensión (la señal más rápida que mantiene este proyecto en movimiento)
- 🐍 Página de PyPI — pypi.org/project/django-orm-lens
- 💚 Patrocinar — github.com/sponsors/FROWNINGdev
📜 Licencia
MIT © FROWNINGdev
Hecho para desarrolladores que se preocupan por su código.
Marketplace · PyPI · GitHub · Issues · Discussions · Sponsor