You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This is the moat feature identified in competitor analysis: no shipped Django extension does ORM query autocomplete well.
Goal: when the user types inside Post.objects.filter(...), complete field names based on the parsed model index, and resolve lookups like author__name through FK edges.
Design sketch:
Detect .filter( / .exclude( / .annotate( call inside a Python file via lightweight regex or textDocument context.
Resolve the QuerySet's base model from the assignment chain (best-effort).
Suggest field names + __lookup traversal from the parsed WorkspaceIndex.
Warn on typos with a diagnostic.
Prior art: the archived django-intellisense extension had a partial implementation worth studying.
Shipped in v0.13.0, live on the Marketplace and Open VSX. Open since day two of the project.
Against the design sketch above
Detect the call — done, and stricter than "lightweight regex". The innermost unclosed ( is found by walking the line with a quote-aware scanner, so label = 'filter(' + x does not open a completion context. Scope is filter, exclude, get, get_or_create, update_or_create, annotate, aggregate, order_by, values, values_list, only, defer, distinct, create, update. A Q(...) / F(...) / Count(...) wrapper is stepped out of, so filter(Q(auth completes auth — not Q.
Resolve the base model — best-effort, and deliberately narrow. The literal <Model>.objects.<method>( shape resolves, including down a chain: Post.objects.filter(published=True).exclude(ti resolves to Post. Anything else returns nothing rather than a guess. An empty list costs the user nothing; a list of fields from the wrong model costs them a debugging session. Assignment-chain inference (qs = Post.objects.all() on an earlier line, then qs.filter() is the obvious next increment and is not in this release.
Fields plus __ traversal — done. author__ walks the FK and offers the related model's fields; two edges compose (parent__author__name); ForeignKey('self') resolves back to its own model; pk is offered everywhere even though it is not a declared field. Lookups are typed rather than a flat list — title__ offers icontains but not gt, views__ offers gte and range but not icontains, created__ adds year/month/hour/date, and BooleanField stays at exact/in/isnull.
Warn on typos with a diagnostic — not in this release. A completion that is silent when unsure is safe; a diagnostic that is wrong when unsure is an error squiggle on correct code. That wants the model resolution from (2) to be stronger first. Worth its own issue rather than holding this one open.
Two details that were invisible until they were wrong, both now under test: _ is a trigger character alongside ( and ,, because a lookup path never leaves a word and VS Code would not re-query after author__ on its own; and the replaced range is the whole lookup path rather than VS Code's default word range, which stops at the last __ and would land author__name as author__author__name.
The decision is completionsAt() in src/ormCompletions.ts — a pure function over one line of text and the parsed index, no vscode import, 30 tests, verified against real parser output rather than only a fixture. Suite is at 176, up from 146.
New setting djangoOrmLens.completions.enabled (default true) for anyone who already has a Python completion source they prefer here.
Activity
feat(codeactions): v0.8 Inline QuickFixes for Django ORM anti-patterns
feat(query): v0.8 WOW-feature #2 — Interactive Query Builder
feat(completions): field and lookup completion inside .filter() (#3)
release: 0.13.1 — the listing leads with autocomplete and is searchab…
FROWNINGdev commentedon Aug 20, 2026
Shipped in v0.13.0, live on the Marketplace and Open VSX. Open since day two of the project.
Against the design sketch above
Detect the call — done, and stricter than "lightweight regex". The innermost unclosed
(is found by walking the line with a quote-aware scanner, solabel = 'filter(' + xdoes not open a completion context. Scope isfilter,exclude,get,get_or_create,update_or_create,annotate,aggregate,order_by,values,values_list,only,defer,distinct,create,update. AQ(...)/F(...)/Count(...)wrapper is stepped out of, sofilter(Q(authcompletesauth— notQ.Resolve the base model — best-effort, and deliberately narrow. The literal
<Model>.objects.<method>(shape resolves, including down a chain:Post.objects.filter(published=True).exclude(tiresolves toPost. Anything else returns nothing rather than a guess. An empty list costs the user nothing; a list of fields from the wrong model costs them a debugging session. Assignment-chain inference (qs = Post.objects.all()on an earlier line, thenqs.filter() is the obvious next increment and is not in this release.Fields plus
__traversal — done.author__walks the FK and offers the related model's fields; two edges compose (parent__author__name);ForeignKey('self')resolves back to its own model;pkis offered everywhere even though it is not a declared field. Lookups are typed rather than a flat list —title__offersicontainsbut notgt,views__offersgteandrangebut noticontains,created__addsyear/month/hour/date, andBooleanFieldstays atexact/in/isnull.Warn on typos with a diagnostic — not in this release. A completion that is silent when unsure is safe; a diagnostic that is wrong when unsure is an error squiggle on correct code. That wants the model resolution from (2) to be stronger first. Worth its own issue rather than holding this one open.
Two details that were invisible until they were wrong, both now under test:
_is a trigger character alongside(and,, because a lookup path never leaves a word and VS Code would not re-query afterauthor__on its own; and the replaced range is the whole lookup path rather than VS Code's default word range, which stops at the last__and would landauthor__nameasauthor__author__name.The decision is
completionsAt()insrc/ormCompletions.ts— a pure function over one line of text and the parsed index, novscodeimport, 30 tests, verified against real parser output rather than only a fixture. Suite is at 176, up from 146.New setting
djangoOrmLens.completions.enabled(defaulttrue) for anyone who already has a Python completion source they prefer here.feat(rules): DOL008 — a lookup name that looks misspelled (#3)