Django ORM Lens
Análise estática de esquema Django para agentes de IA — 10 ferramentas somente leitura (models, relações, diagramas ER, DAG de migrações, varredura N+1) sem banco de dados e sem inicialização do Django.
Documentação
English · Русский · Español · 中文
Django ORM Lens
Diagramas ER, detecção de N+1 e verificações de risco de migração para Django — sem inicializá-lo.
Todo o seu grafo de modelos — ao vivo na barra lateral do editor, controlando seu CI e respondendo ao seu agente de IA via MCP. Tudo a partir de análise estática: sem banco de dados, sem runserver, sem venv funcional.
Substitui: graph_models + django-schema-graph + diagramas ER desenhados à mão + arqueologia de grep.
Destaque em Django News #347 · PyCoder's Weekly #746
⚡ 10 segundos para o primeiro insight
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
Clone frio, venv quebrado, sem módulo de settings — você ainda vê todos os apps e modelos do projeto, depois os loops N+1 e migrações arriscadas, direto no seu terminal. (uvx é do uv; pipx run funciona da mesma forma.)
Depois escolha sua superfície — três distribuições, um núcleo de parser:
| Você é | Instalação | Você recebe |
|---|---|---|
| Usuário de editor — VS Code / Cursor / Windsurf / VSCodium | code --install-extension frowningdev.django-orm-lens | Autocompletar de campos no .filter(), árvore na barra lateral, diagrama ER ao vivo, cards de hover, 18 regras de lint com QuickFixes |
| Usuário de terminal / CI | pip install django-orm-lens | 17 subcomandos, SARIF + anotações de PR, hooks de pre-commit, uma GitHub Action |
| Usuário de agente de IA — Cursor / Claude Code / Aider / Zed / Continue | pip install "django-orm-lens[mcp]" | 13 ferramentas MCP somente leitura respondendo perguntas de schema a partir da fonte da verdade |
A configuração do MCP é um bloco JSON — veja Integrações. Aponte DJANGO_ORM_LENS_ROOT para o caminho absoluto do seu projeto Django.
🆓 Recursos de nível pago, gratuitos e MIT
Revisão de schema é uma categoria paga em quase todo lugar. Um bot que revisa cada pull request, análise que segue um queryset além da função onde foi criado, uma verificação que detecta drift de schema, conselhos de índice baseados em estatísticas reais de tabela — tudo isso normalmente fica atrás de uma assinatura por usuário ou por banco de dados.
Tudo isso está aqui, licenciado sob MIT, sem limite de tier, sem contagem de assentos, sem conta e sem telemetria:
| Recurso normalmente vendido como tier pago | Aqui |
|---|---|
| Bot de revisão de PR para mudanças de schema — posta uma vez, depois atualiza no lugar | blast-radius + a Action |
| Análise que segue um queryset entre funções | nplusone |
| Detecção de drift de schema | drift |
| Propostas de índice a partir do uso observado de QuerySet | suggest-indexes |
| Risco de migração ponderado contra tamanhos reais de tabela | blast-radius --stats |
| Raio de impacto de uma migração destrutiva | blast-radius |
| Impacto entre camadas da remoção de um campo | impact |
Não existe tier Pro, e nenhum está planejado. Se a ferramenta economizar uma tarde para você, uma estrela é todo o pedido.
📊 Tração
Se a ferramenta economizar um
grepna próxima vez que você mexer em um projeto Django estranho — uma estrela ajuda outros a encontrá-la.
📈 Crescimento de estrelas
⚡ Instalação
VS Code / Cursor / Windsurf (VS Code Marketplace):
code --install-extension frowningdev.django-orm-lens
VSCodium / code-server / Gitpod / qualquer fork OSS do Code (Open VSX):
codium --install-extension frowningdev.django-orm-lens
Ou pesquise Django ORM Lens na visualização de Extensões — mesmo publisher frowningdev em ambos os registros.
Agentes de terminal e codificação com IA:
pip install django-orm-lens # CLI only
pip install "django-orm-lens[mcp]" # + MCP server for AI agents
Requer Python 3.9+. Zero dependências de runtime para a CLI.
Docker (v0.6+):
docker run --rm -v "$PWD:/workspace" ghcr.io/frowningdev/django-orm-lens scan --path .
Multi-arquitetura (amd64 + arm64). Sem Python necessário no host. Bom para CI e auditorias pontuais.
🎯 O problema
Funciona offline. Funciona em um venv quebrado. Funciona no laptop de outra pessoa. Funciona no CI.
Você abre um projeto Django. Ele tem 20 apps. Você precisa responder a uma pergunta simples:
"Qual app é dono do modelo
Order, e como ele está conectado aoUser?"
Hoje, isso significa: Ctrl+P, "models", rolar por 30 resultados, abrir cinco arquivos, Ctrl+F por class Order, ler 400 linhas de strings ForeignKey('otherapp.Something'), tentar lembrar o que você aprendeu dois arquivos atrás.
Meio dia perdido. Toda vez. Em todo projeto.
✨ Com Django ORM Lens
📚 Uma árvore de tudoCada app → cada modelo → cada campo → cada opção Ícones distinguem |
🕸️ Um diagrama ER ao vivoUm comando abre um diagrama de entidade-relacionamento Mermaid de todo o seu schema. Veja-o redesenhar enquanto você edita. Exporte para SVG.
|
🔎 Hover para relaçõesPasse o mouse sobre |
🧭 Ir para definiçãoClique em qualquer campo na árvore → o cursor pousa na linha exata. Filtre a árvore por nome de app ou modelo. Pacotes |
⚡ Zero configuraçãoSem |
🎨 UI nativa do VS CodeTema escuro. Tema claro. Seu tema. Segue seu tema de ícones, sua fonte, seus atalhos de teclado. Nada chamativo, nada com marca. |
🚀 Recursos avançados
💥 Raio de impactoA pergunta no momento da revisão que uma mudança de schema realmente levanta: o que isso atinge? Cada operação de migração destrutiva se torna um alvo carregando seus riscos, cada lugar no código que ainda a lê e — para operações de modelo inteiro — o efeito cascata.
|
🧭 Drift de schema
A própria verificação do Django precisa de um módulo de settings funcional, um registro de apps importável e todas as dependências instaladas — indisponível em um clone frio ou venv quebrado, que é exatamente quando a resposta é mais barata de agir. Apenas a direção perigosa falha o build: um campo declarado mas nunca migrado significa que a coluna não existirá, e a primeira consulta que o toca gera erro. |
🎯 Diagnósticos inline e QuickFixes (18 regras)Análise estática sobre arquivos Suprima inline com |
🧪 Gerador de factoriesClique com o botão direito em qualquer modelo → scaffold Também disponível como CodeLens acima de cada classe de modelo. |
🕰 Diff de schema com viagem no tempoEscolha um Renomeações são eventos de primeira classe, nunca |
🔎 Análise de impacto"O que quebra se eu remover este campo?" — clique com o botão direito em um campo ou modelo → varredura em todo o workspace agrupada por camada Django (models, serializers, forms, admin, views, urls, templates, tests, migrations). Os resultados carregam uma etiqueta de confiança Certo / Provável / Possível. Lida com refs de string ORM ( |
⚡ Construtor de consultas interativoClique com o botão direito em um campo ou modelo → escolha um template → snippet inserido no cursor (com tab-stops) ou em um buffer novo sem título.
|
🎨 Reformulação da barra lateral
Badges |
📸 Como parece
Amostra ao vivo — saída real de django-orm-lens er, renderizada pelo GitHub aqui mesmo:
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]"
Também incluído na extensão:
- 🕸️ Diagrama ER ao vivo — setas de cardinalidade Mermaid, rótulos de borda (
CASCADE,through Model,as related_name), consciente de tema, exportação SVG com um clique - 🔎 Cartões de foco — sobre qualquer
ForeignKey('app.Model')ouManyToManyField(...), com link de salto em um clique - 🧭 CodeLens — acima de cada linha de
class Model: contagem de campos, contagem de relações e uma ação Abrir diagrama ER - 🎨 Temas nomeados —
auto/default/dark/forest/neutralpara o webview do diagrama
🤖 Para terminais e agentes de IA de codificação
O mesmo parser que alimenta a extensão do VS Code é distribuído como um pacote Python independente — com um servidor MCP (Model Context Protocol) opcional, para que qualquer agente de IA compatível com MCP possa navegar pelo seu esquema Django sem importar o Django ou iniciar seu aplicativo.
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,driftestats-sqlsão fornecidos na py-1.7.0 e versões posteriores.
Todo comando aceita --path <dir> e --exclude <glob>. nplusone / migration-risk / diff saem com código 1 quando há achados — use-os no CI para bloquear PRs com regressões.
Servidor MCP
Registre-o uma vez com seu agente e ele expõe treze ferramentas somente leitura:
| Ferramenta | Finalidade |
|---|---|
list_apps | Todos os aplicativos Django no workspace com contagens de modelos |
list_models | Lista plana de app.Model, com filtro opcional por aplicativo |
describe_model | Detalhes completos de campo / relação / Meta para um modelo |
find_relations | Relações de entrada e saída para um modelo |
cascade_preview | Raio de impacto de um delete(), agrupado por on_delete |
er_diagram | Diagrama ER — mermaid / dbml / d2 / plantuml / dot |
describe_migration_dependency | DAG de migrações por aplicativo: raízes, folhas, dependências entre aplicativos |
suggest_indexes | Propostas de Meta.indexes a partir do uso observado de QuerySet |
signal_graph | Grafo remetente→sinal→handler a partir de decoradores @receiver |
blast_radius | O que uma migração destrutiva atinge: seus riscos, o código que ainda a lê, o impacto em cascata |
drift | makemigrations --check sem iniciar o Django — migrações comparadas com models.py |
impact | Toda referência a um campo ou nome de modelo, agrupada por camada Django |
nplusone_scan | Achados estáticos de N+1 para todo o workspace |
# Start it directly
django-orm-lens-mcp
# Or via the CLI subcommand
django-orm-lens mcp
Resolução de workspace (py-1.3.0+). Toda ferramenta aceita um argumento opcional
workspace_root na chamada. Prioridade de resolução: argumento explícito →
$DJANGO_ORM_LENS_ROOT → diretório de trabalho atual. Caminhos inválidos ou não-Django
retornam um envelope estruturado
({"error": "WORKSPACE_NOT_DJANGO", "hint": "…"}) em vez de resultados vazios,
para que o agente possa se autocorrigir. Sandbox opcional via
DJANGO_ORM_LENS_ALLOWED_ROOTS (separado por ; no Windows, : em outros lugares).
🛡️ Proteja seu CI
Regressões de esquema são mais baratas de detectar no momento em que entram em um PR. Quatro maneiras sem configuração para bloqueá-las:
Bot de PR de raio de impacto — a revisão completa do esquema em um único comentário, atualizado no lugar a cada push em vez de um novo comentário a 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 }}
O comentário vai ao ar antes de o job falhar, então um PR bloqueado ainda explica o motivo. only-changed lê a lista de arquivos do PR da API em vez de git diff, porque actions/checkout usa como padrão fetch-depth: 1 e o commit base não está no histórico local. Em eventos push, ambas as flags pulam com um aviso em vez de falhar, então um único workflow cobre os dois gatilhos.
A Action instala a partir do PyPI, então
blast-radiusedriftprecisam da py-1.7.0 ou posterior — fixe-a comversion: 1.7.0se seu workflow não puder variar. Para executar uma versão não publicada, adicioneinstall: falsee instale a fonte você mesmo; o workflow deste repositório faz exatamente isso, e é o que verifica a Action em todo PR.
pre-commit — dois hooks, nada para 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 — os achados aparecem como anotações de PR com zero permissões extras:
- uses: FROWNINGdev/django-orm-lens@action-v1
with:
command: migration-risk # or: nplusone
format: github # ::error / ::warning annotations on the diff
SARIF → Code Scanning — os achados vão para a aba Segurança do repositório:
- 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
Os códigos de saída são nativos de CI: diff e nplusone saem com 1 em achados, migration-risk e blast-radius saem com 1 em achados críticos, drift sai com 1 quando um campo é declarado mas nunca migrado. Adicione --exit-zero para o modo somente relatório.
🔌 Integrações
| Cliente | Como habilitar | Status |
|---|---|---|
| VS Code | code --install-extension frowningdev.django-orm-lens | ✅ |
| Cursor | mesmo VSIX + entrada MCP opcional em ~/.cursor/mcp.json | ✅ |
| Windsurf / VSCodium / qualquer fork do Code | instale o VSIX do Marketplace ou dos GitHub Releases | ✅ |
| Aider | adicione django-orm-lens-mcp ao seu mcp.json | ✅ (via MCP) |
| Continue.dev | registre o servidor MCP em ~/.continue/config.json | ✅ (via MCP) |
| Zed | registre o servidor MCP nas configurações do Zed | ✅ (via MCP) |
| Qualquer cliente compatível com MCP | aponte command para django-orm-lens-mcp, defina DJANGO_ORM_LENS_ROOT | ✅ |
| pre-commit | repo: https://github.com/FROWNINGdev/django-orm-lens + dois IDs de hook | ✅ |
| GitHub Actions | uses: FROWNINGdev/django-orm-lens@action-v1 — anotações ou SARIF | ✅ |
| Descobrível via MCP Registry | diretório oficial de servidores Model Context Protocol | ✅ |
| Terminal simples / CI | pip install django-orm-lens && django-orm-lens scan | ✅ |
Exemplo: Cursor / qualquer cliente MCP
{
"mcpServers": {
"django-orm-lens": {
"command": "django-orm-lens-mcp",
"env": { "DJANGO_ORM_LENS_ROOT": "/abs/path/to/your/project" }
}
}
}
⚡ Desempenho
A suíte de regressão analisa os grafos de modelos vendidos de Zulip, Saleor, Wagtail, django CMS e Mezzanine — 59 modelos em 13.478 linhas de models.py do mundo real — em cerca de 20 ms de ponta a ponta em um laptop (21 ms melhor-de-3 no corpus de fixtures douradas do repositório; um guard de <2 s roda no CI em cada célula da matriz).
Reproduza você mesmo:
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 quem é isso
- Desenvolvedores Django que entram em um codebase com 10+ aplicativos e se perdem na bagunça de
models.py. - Engenheiros contratados / freelancers que precisam entender um projeto Django desconhecido na primeira hora, não na primeira semana.
- Equipes integrando novos contratados que querem uma visão de esquema em um relance sem montar infraestrutura de documentação.
- Usuários avançados de agentes de IA (Cursor / Aider / Zed / Continue / qualquer cliente compatível com MCP) que precisam que o agente responda perguntas de esquema com precisão — sem dar a ele credenciais de banco de dados ou iniciar o Django.
- Pipelines de CI que verificam a forma do esquema (por exemplo, "quebramos acidentalmente um
related_name?") sem importar o projeto. - Devs indie solo com um venv quebrado ou no laptop de outra pessoa — sem
runserver, semmanage.py migrate, ainda funciona.
🗺️ Posição de mercado
Django ORM Lens fica na interseção de ferramentas de editor e ferramentas de agente de IA — um espaço que nenhum pacote existente cobre:
| Segmento | Opção existente | O que custa para você |
|---|---|---|
| Iniciar-e-grafo | django-extensions graph_models | Requer Graphviz + configurações do Django + uma URL de banco funcional |
| Visualizador baseado na web | django-schema-graph | Requer um servidor Django em execução; hospeda mais uma coisa para quebrar |
| Painel administrativo | Django Admin | Requer runserver + autenticação + banco de dados — ótimo para dados, não para arquitetura |
| Plugin de editor | Estrutura Django do PyCharm | Limitado ao PyCharm; sem CLI, sem história de agente de IA |
| Servidor MCP | (nenhum até agora) | Agentes de IA adivinham seu esquema a partir do código-fonte, de forma imperfeita |
Django ORM Lens é a única ferramenta que oferece três superfícies a partir de um único parser: uma extensão do VS Code (qualquer fork do Code), uma CLI sem dependências (terminais + CI) e um servidor MCP (agentes de IA). Tudo estático. Tudo gratuito. Tudo MIT.
🤔 Como isso é diferente?
| Django ORM Lens | django-extensions graph_models | django-schema-graph | Django Admin | Estrutura Django do PyCharm | |
|---|---|---|---|---|---|
| Funciona sem um projeto Django inicializável | ✅ | ❌ | ❌ | ❌ | ⚠️ |
| Sem instalação (sem graphviz, sem servidor) | ✅ | ❌ | ❌ | ❌ | ❌ (precisa do PyCharm) |
| Funciona no VS Code / Cursor / qualquer fork do Code | ✅ | ❌ | ❌ | ❌ | ❌ |
| Árvore lateral dentro do editor | ✅ | ❌ | ❌ | ❌ | ✅ |
| Diagrama ER ao vivo | ✅ | ✅ | ✅ | ❌ | ❌ |
Cartões de foco em ForeignKey | ✅ | ❌ | ❌ | ❌ | ⚠️ |
| CodeLens em classes de modelo | ✅ | ❌ | ❌ | ❌ | ❌ |
Suporte a pacote models/ dividido | ✅ | ⚠️ | ⚠️ | ✅ | ✅ |
| CLI para terminal / CI | ✅ | ⚠️ | ❌ | ❌ | ❌ |
| Servidor MCP para agentes de IA | ✅ | ❌ | ❌ | ❌ | ❌ |
| Descobrível no MCP Registry | ✅ | ❌ | ❌ | ❌ | ❌ |
| Gratuito e de código aberto (MIT) | ✅ | ✅ | ✅ | ✅ | ❌ (IDE paga) |
| Suporte a versões do Django | 4.0 – 5.2 | mais recente | 3.2 – 4.1 (desatualizado desde 2023) | mais recente | mais recente |
django-schema-graphnão é atualizado desde 2023-05 e não testa Django 5.x.
Quando você quer outra coisa
Limites honestos: perfil de uma requisição ao vivo → django-debug-toolbar. Perfil histórico de requisições → django-silk. Asserções de contagem de consultas dentro de uma suíte de testes → django-perf-rec. APM de produção em tráfego real → Scout / Sentry. Django ORM Lens permanece deliberadamente estático — é a camada que funciona antes mesmo de o aplicativo iniciar, e a única que seu CI e seu agente de IA podem usar em qualquer checkout.
⚙️ Configuração
Os padrões são opinativos e sensatos. Se precisar ajustar:
// .vscode/settings.json
{
"djangoOrmLens.excludeGlobs": [
"**/migrations/**",
"**/node_modules/**",
"**/venv/**",
"**/.venv/**",
"**/env/**"
],
"djangoOrmLens.autoRefresh": true
}
| Configuração | Tipo | Padrão | O que faz |
|---|---|---|---|
djangoOrmLens.excludeGlobs | string[] | Veja acima | Padrões glob para pular ao escanear |
djangoOrmLens.autoRefresh | boolean | true | Reescaneia em mudanças de models.py |
djangoOrmLens.codeFixes.enabled | boolean | true | Interruptor mestre para os diagnósticos DOL### + QuickFixes |
djangoOrmLens.rules | object | {} | Severidade por regra: { "DOL007": "off", "DOL013": "error" } |
djangoOrmLens.rulesSelect | string[] | [] | Seleção estilo Ruff. ["DOL0"] executa apenas regras de queryset+modelo |
djangoOrmLens.rulesIgnore | string[] | [] | Ignorar estilo Ruff. ["DOL03"] silencia regras de formulário/visão |
🔬 Catálogo de regras
Dezoito verificações do lado do editor (DOL001–DOL041) com códigos estilo Ruff, severidade por regra e aplicabilidade estilo Clippy — além de dezesseis regras de risco de migração do lado da CLI e o analisador estático de N+1. Toda regra agora tem sua própria página de documentação.
| Categoria | Regras | Exemplos |
|---|---|---|
| Queryset | DOL001–DOL007 | .count() > 0 → .exists(), acesso a FK em loops (N+1) |
| Definição de modelo | DOL011–DOL015 | ForeignKey sem on_delete, null=True em campos de string |
| Datetime | DOL021–DOL022 | datetime.now() → timezone.now() |
| Formulários / visões | DOL031–DOL032 | locals() em render(), Meta.fields = '__all__' |
| SQL bruto | DOL041 | SET enable_hashjoin = off, plan_cache_mode, jit overrides em código de aplicativo |
| Riscos de migração | 16 regras | NOT NULL adicionado sem padrão, builds de índice com bloqueio de tabela, migrações de dados irreversíveis |
| N+1 estático | 1 analisador | Acesso a FK/M2M em loops sem select_related / prefetch_related |
→ Referência completa de regras — todo código com exemplos ruins/bons, comportamento do QuickFix e sintaxe de supressão.
Suprimir inline
# 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
A aplicabilidade segue o Clippy do Rust: correções seguras podem ser aplicadas automaticamente ("Corrigir tudo"), correções sugeridas são oferecidas como QuickFix, mas revisadas, achados inseguros nunca são aplicados automaticamente. As correções são separadas dos analisadores (estilo Roslyn), então uma regra pode ganhar vários corretores ao longo do tempo sem tocar na lógica de detecção.
🧭 Comandos
Abra a paleta de comandos (Ctrl+Shift+P / Cmd+Shift+P) e digite "Django ORM Lens":
| Comando | O que faz |
|---|---|
Django ORM Lens: Refresh | Força o reescaneamento do workspace |
Django ORM Lens: Show ER Diagram | Abre o diagrama ER Mermaid lado a lado |
Django ORM Lens: Filter Models | Filtra a árvore por nome de app / modelo / campo |
Django ORM Lens: Clear Filter | Restaura a árvore completa |
Django ORM Lens: Jump to Model | Programático — acionado por cliques na árvore e cards de hover |
Django ORM Lens: Find Reverse References | Clique com o botão direito em um modelo — QuickPick de cada FK apontando para ele |
Django ORM Lens: Generate factory_boy Factory | Clique com o botão direito em um modelo ou use CodeLens — gera um scaffold de DjangoModelFactory |
Django ORM Lens: Schema Diff (Time-Travel) | Escolha dois commits — obtenha um diff tipado como buffer markdown |
Django ORM Lens: Find Impact (What Uses This?) | Clique com o botão direito em um campo ou modelo — varredura de referências em todo o workspace |
Django ORM Lens: Build Query (Insert Snippet) | Clique com o botão direito em um campo ou modelo — escolha um template ORM |
🗺️ Roadmap
Entregue
- Árvore da barra lateral agrupada por app
- Diagrama ER Mermaid ao vivo
- Cards de hover sobre
ForeignKey('app.Model') - Filtro da árvore por nome
- Suporte a pacotes divididos
models/ - Exportação do diagrama ER como SVG
- CLI Python + servidor MCP para terminais e agentes de IA
- Visualização de boas-vindas para workspaces vazios
- Ir para definição seguro para caminhos e markdown de hover sanitizado
- v0.3.0 — CodeLens acima de cada classe de modelo (
N fields · N relations · Open ER diagram) - v0.3.0 — Rótulos de arestas no diagrama (
CASCADE,SET_NULL,PROTECT,related_name) - v0.3.0 — Temas de cores nomeados (
auto/default/dark/forest/neutral) - v0.3.1 —
through_modelem arestas M2M (contribuição de @kingrubic) - v0.3.1 — Listado no Registro MCP oficial + Glama.ai
- v0.6.0 — CLI
nplusone— detector estático de N+1 (acesso a FK/M2M dentro de loops semselect_related/prefetch_related) - v0.6.0 — CLI
migration-risk— sinaliza operações arriscadas emmigrations/*.py(15 regras hoje) - v0.6.0 — CLI
diff— compara dois dumps de schema JSON para revisão de PR - v0.6.0 — Minimapa do diagrama ER codifica por cores os nós por app Django
- v0.6.0 — Traduções do README: 🇷🇺 Russo, 🇪🇸 Espanhol, 🇨🇳 Chinês
- v0.6.0 — Imagem Docker no GHCR:
docker run ghcr.io/frowningdev/django-orm-lens - v0.7.0 —
settings.AUTH_USER_MODELresolve em todos os lugares: relações reversas n+1, remetentes de sinais, Mermaid ER, webview do VS Code, painel de relações de entrada, ER React - v0.7.0 — Parser de campos baseado em AST:
ForeignKey(on_delete=CASCADE, to='User')resolve independentemente da ordem dos kwargs (paridade Python + TS) - v0.7.0 — Helpers compartilhados públicos:
find_user_model,resolve_related_tail,find_model,iter_workspace_py_files(Python) +findUserModel,resolveRelatedTail(TS) - v0.7.0 —
--verbosenão percorre mais a árvore duas vezes;WorkspaceIndex.scanned_filescarrega a contagem - v0.7.3 — Anotações de tipo PEP-526 em campos (
jti: CharField[str] = models.CharField(...)) agora são analisadas — relatado por @jsabater (#25) com um repro limpo do Django Ninja 1.6 - v0.7.4 — Cabeçalhos de classe genéricos PEP-695 (Python 3.12+):
class Container[T](models.Model):agora é analisado - v0.7.5 — Módulo de modelos com alias (
from django.db import models as m) e pacotes de campos de terceiros (jsonfield.JSONField) agora são detectados - v0.7.6 — Corpos de modelo indentados com tabulação agora são analisados (editores que usam tabs por padrão não mostram mais modelos vazios)
- v0.8.0 — QuickFixes inline: 16 regras (
DOL001..DOL032) com severidade por regra + selecionar/ignorar estilo Ruff +# django-orm-lens-disable-next-lineinline - v0.8.0 — Gerador de factories: scaffold
factory_boya partir de qualquer modelo com provedores Faker chaveados por tipo de campo - v0.8.0 — Diff de Schema com Viagem no Tempo: escolha dois commits → diff markdown tipado com detecção de renomeação de primeira classe
- v0.8.0 — Análise de impacto: varredura de referências de campos em todo o workspace em cada camada Django com tags de confiança Certa/Provável/Possível
- v0.8.0 — Construtor de Consultas Interativo: clique com o botão direito → template → snippet inserido no cursor, ciente da gramática (FK recebe
.select_related,related_namerespeitado) - v0.8.0 — Reformulação da UX da barra lateral:
TreeItem.idestável, tooltipsMarkdownStringcom deep-linkscommand:, badgesFileDecorationProvider,TreeView.badgena barra de atividades, três estadosviewsWelcomecom gate por condição
v1.5.0 — a onda "um núcleo, três superfícies"
- CI formata: SARIF 2.1.0 + anotações de PR
--format githubparanplusoneemigration-risk - Quatro analisadores promovidos de somente-MCP para o CLI:
suggest-indexes,signals,migration-deps,cascade -
er --format dbml | d2 | plantuml | dot— exportações de diagramas padrão da comunidade (dbdiagram.io, D2, PlantUML, Graphviz —dotcontribuído por @JJordan0C) - Três novas regras de risco de migração:
runpython_no_reverse,alter_unique_together_lock,alter_index_together_deprecated— 15 no total - Hooks de pre-commit (
django-orm-lens-nplusone,django-orm-lens-migration-risk) + GitHub Action composta -
docs/rules/— uma página de documentação para cada regra (19 páginas) - Suíte de regressão com snapshots dourados sobre 59 modelos reais (Zulip / Saleor / Wagtail / django CMS / Mezzanine); ruff + mypy agora controlam o CI
- Grafo de dependências de migração —
migration-deps(texto / json / mermaid)
py-1.7 → 1.8 — a onda de inteligência de schema
-
blast-radius— riscos de migração unidos ao que ainda lê o schema que eles tocam, como bot de PR (comment: true, fixado,only-changed) -
drift—makemigrations --checksem iniciar o Django -
impact <name>— o que ainda referencia um modelo ou campo, agrupado por camada Django -
blast-radius --stats+stats-sql— contagens opcionais de linhas de produção a partir de SQL somente-leitura que você mesmo executa (a ferramenta nunca guarda credencial de banco) -
nplusoneresolve entre funções — um queryset retornado por um helper é seguido até o loop que o consome -
blast_radius,drifteimpactexpostos como ferramentas MCP — treze ferramentas para agentes de IA -
driftdocumenta suas marcas!!/~no relatório e em--help— relatado por @sevdog (#57) -
driftsegue herança de bases abstratas — os campos de uma base abstrata contam como os do filho concreto, como o Django os trata — relatado por @sevdog (#58) -
suggest-indexreconhece os índices que o Django já criou — chave primária (pkeidsão uma única consulta),db_index,unique, chaves estrangeiras,unique_together,UniqueConstraint— relatado por @sevdog (#60), mesma causa encontrada independentemente por @RinZ27 (#61) - Uma sexta fixture dourada — Read the Docs se junta a Zulip, Saleor, Wagtail, django-CMS e Mezzanine, colocando o parser sob 75 modelos e 538 campos de Django real — contribuído por @JJordan0C (#62, fechando #51)
- O
TaggableManagerdo django-taggit é lido como o M2M que ele é — através detaggit.TaggedItemparataggit.Tag, overridesthrough=respeitados, tanto no parser Python quanto no TypeScript — contribuído por @Guflly (#63, fechando #50) -
DOL021declara o padrãoUSE_TZcorretamente —Falseaté Django 4.2,Truea partir de 5.0, com oUSE_TZ = Truedo templatestartprojectdesde 4.0 destacado como a coisa separada que é — e não afirma mais quetimezone.now()está sempre ciente de UTC — encontrado por @Justine0211 enquanto traduzia a página (#52) - A fixture
parity_input.pycarrega o importmodelsque ummodels.pyreal teria — contribuído por @RinZ27 (#64)
py-1.9 → 1.12 — a onda de checkouts reais
Encontrado executando o CLI sobre checkouts reais de django-oscar, django-guardian, django-allauth e django-cms em vez de fixtures. Cada um desses era invisível para uma suíte de testes verde, e dois deles faziam a ferramenta responder com confiança algo falso.
- Modelos declarados dentro de um bloco no nível do módulo são analisados — o idioma de modelo trocável (
if not is_model_registered(...):e depois umclassindentado) que todo framework Django plugável usa, contra a descoberta de classes ancorada em^class. django-oscar passou de 12 modelos, todos do seu próprio diretóriotests/, para 82. Todos os seis snapshots dourados permaneceram byte-idênticos: uma classe na coluna 0 é analisada exatamente como antes -
abstract_models.pyé lido junto commodels.py— frameworks plugáveis mantêm a base abstrata lá e deixammodels.pysegurando apenas a subclasse concreta, então 72 dos 83 modelos do django-oscar reportavam zero campos entre eles. Agora são 8, e esses 8 estão corretos: eles subclassificam modelos concretos, onde a herança multi-tabela deixa as colunas na tabela do pai -
driftnão falha mais um build por dois diretórios de app compartilhando o mesmo nome — o estado de migração reproduzido é mesclado por nome de app, combinando com como o lado declarado já é chaveado. Em um checkout real do django-guardian, a contagem de bloqueios vai de 1 → 0 e a linha duplicada contraditória desaparece, enquanto um campo genuinamente não migrado ainda bloqueia - Modelos django-mptt não são mais invisíveis —
MPTTModelé uma base reconhecida, eTreeForeignKey/TreeOneToOneField/TreeManyToManyFieldsão reportados como os campos Django que eles subclassificam, entãoTreeForeignKey('self', ...)desenha exatamente a auto-aresta que umForeignKey('self', ...)simples faz. Nenhuma dependênciadjango-mptté adicionada — o parser continua funcionando contra um venv quebrado. Oproduct.Categorydo Saleor e sua arestachildrenagora aparecem no snapshot dourado: 76 linhas adicionadas, nenhuma removida (fechando #49) - O servidor MCP reporta sua própria versão —
FastMCPnão encaminha nenhuma, então o SDK caía paraimportlib.metadata.version("mcp")e cada respostainitializenomeava o número de release do projeto errado para o cliente
v0.9 → v0.12.1 — a extensão alcança
- v0.9.0 — Rastreamento parcial de
UniqueConstraintno Time-Travel Schema Diff:add/drop/change/renamecomo eventos tipados, comfromConditioncarregando o predicado anterior à mudança, para que um comentário de revisão possa mostrarQ(is_primary=True) → Q(is_primary=True, deleted=False), e uma renomeação não aparecendo mais como um paradd + dropcom perda de dados. Várias restrições sem nome em um único modelo são agrupadas em#anon-<index>em vez de colapsarem em um único evento. Motivado por django-extensions #1813, ondesqldiffdescarta o predicadocondition=e os revisores de migração nunca veem o que mudou - v0.10.0 — A detecção de camadas da análise de impacto agora roda no caminho relativo ao workspace. Antes, ela correspondia a
/tests/e/views.pyem qualquer lugar no caminho absoluto do arquivo, então um projeto clonado em qualquer diretório chamadotests— ou um monorepo comservices/tests/acima — fazia todos os arquivos serem reportados como aquela camada,views.pycomo teste,admin.pycomo teste. Também: mensagens do webview validadas por origem em vez de por fonte, e migrações folha conflitantes detectadas — duas migrações reivindicando o mesmo pai, algo que o Django só reclama na hora demigrate - v0.10.1 — A listagem no Marketplace menciona análise de impacto, raio de explosão e deriva de esquema, e diz claramente que a ferramenta é gratuita e MIT, sem camada Pro. A página da loja ainda descrevia a extensão como uma barra lateral e um diagrama ER — o que ela era duas versões atrás — então ninguém que buscava esses recursos a encontrava. Os metadados só têm efeito na publicação, por isso precisou de um lançamento próprio
- v0.11.0 — A metade TypeScript do suporte a django-mptt, lançada como versão própria em vez de incorporada a uma posterior: entre o envio do py-1.12.0 e este build, a CLI e a extensão discordavam sobre o que um esquema django-mptt contém, que é exatamente a falha que o fixture dourado compartilhado existe para evitar
- v0.12.0 — A extensão pede uma estrela no GitHub na terceira abertura iniciada pelo usuário do diagrama ER. Não na instalação: um aviso que chega antes de a ferramenta ter feito qualquer coisa é dispensado reflexivamente, e essa dispensa é permanente na mente do usuário. Atualizações da barra lateral que re-renderizam um painel já aberto não são contadas — não são o usuário pedindo nada. "Depois" e "Não perguntar de novo" são armazenados como estados separados, então um adiamento rearma a pergunta exatamente uma vez, doze aberturas depois; dois avisos é o máximo por vida útil. A política é uma função pura coberta por seis testes que não precisam de host VS Code
- v0.12.1 — Exportar como SVG gravava um arquivo inaberto.
toSvgretorna marcação com codificação percentual, enquantotoPngretorna base64; o caminho de salvamento assumia base64 para qualquer coisa começando comdata:, e decodificar base64 de texto com codificação percentual não falha — o decodificador descarta silenciosamente todo caractere fora do seu alfabeto e retorna bytes. Um documento<svg>de 48 caracteres chegava ao disco com o nome certo, um tamanho plausível e nenhum conteúdo válido em lugar algum. A codificação de transferência agora é lida do cabeçalho da URL de dados em vez de adivinhada pelo prefixo
Próximo
- v0.13.0 — Autocompletar campos dentro de
.filter()/.exclude()/.get()(#3) - v0.10.0 — Caixas de seleção de app / modelo: desmarque um app ou modelo na barra lateral para removê-lo do diagrama ER
- Mecanismo de regras DOL portado para a CLI Python — um catálogo de regras, três superfícies
Depois
- Suporte a campos de terceiros —
django-model-utils(django-taggitenviado no py-1.11.0,django-mpttno py-1.12.0 / v0.11.0) - Plugin JetBrains / PyCharm (se houver demanda)
Vote com 👍 na issue correspondente.
❓ FAQ
Você envia algum dos meus códigos para um servidor?
Não. Cada byte permanece na sua máquina. O parser é TypeScript puro (extensão) ou Python puro (CLI). Sem chamadas de LLM, sem telemetria, sem analytics, sem relatórios de erro. O renderizador Mermaid roda dentro do sandbox do webview do VS Code.
Funciona com Poetry / uv / conda / sem venv algum?
Sim. A extensão lê o código-fonte Python diretamente — ela não importa o Django e não se importa com qual gerenciador de pacotes você usa. A CLI exige Python 3.9+, mas só isso.
Meus modelos estão divididos em vários arquivos dentro de um pacote models/. Isso funciona?
Sim, desde a v0.2.0. Tanto a extensão quanto a CLI percorrem
models/*.py além do clássico models.py.
Posso usar com serializers DRF, Wagtail, Oscar ou modelos base de terceiros?
Qualquer classe que pareça um modelo Django é capturada: subclasses de
models.Model, bases abstratas começando com Abstract, mixins comuns terminando em Mixin, e nomes de base conhecidos como TimeStampedModel ou PolymorphicModel. Classes que não são modelos (ModelAdmin, ModelSerializer, Form, View, Manager, …) são filtradas.
Quais agentes de IA podem usar o servidor MCP?
Qualquer cliente compatível com MCP — Cursor, Aider, Continue.dev, Zed e qualquer outra ferramenta que fale o protocolo. Basta apontar
command para o binário instalado django-orm-lens-mcp. Veja a seção Integrations.
Como bloqueio regressões de esquema no CI?
Três maneiras, todas sem configuração: os dois pre-commit hooks, a GitHub Action composta (
uses: FROWNINGdev/django-orm-lens@action-v1 com format: github para anotações em PRs), ou --format sarif canalizado para github/codeql-action/upload-sarif na aba Segurança. diff / nplusone saem com código 1 em achados, migration-risk sai com código 1 em achados críticos.
Existe uma versão JetBrains / PyCharm?
Ainda não. A janela de ferramentas Django Structure do PyCharm já é boa, então o delta de valor é menor. Se gente suficiente pedir, vale a pena fazer.
🆘 Suporte
- 🐛 Relatórios de bug — GitHub Issues (inclua um snippet mínimo de
models.py) - 💡 Pedidos de recurso / ideias — GitHub Discussions
- 📝 Avaliações no Marketplace — avalie a extensão (o sinal mais rápido que mantém este projeto em movimento)
- 🐍 Página no PyPI — pypi.org/project/django-orm-lens
- 💚 Patrocinar — github.com/sponsors/FROWNINGdev
📜 Licença
MIT © FROWNINGdev
Feito para desenvolvedores que se importam com seu código.
Marketplace · PyPI · GitHub · Issues · Discussions · Patrocinar