templates — template coherence¶
ID: templates
Since: 0.6.0
Order: 45 (between forms_meta and urls)
Needs DB: no
Severity: WARNING (missing static) / ERROR (unknown URL name, template syntax)
What it catches¶
Three silent-problem patterns in .html files:
{% url 'name' %}pointing at a URL name that the resolver doesn't know about. Django only raisesNoReverseMatchat render time, so a typo in a template behind an auth wall rides in main until a user finally hits the page.{% static 'path/to/asset.ext' %}that no staticfiles finder resolves. Broken asset paths don't surface atcollectstatictime unless you read its verbose output.- Malformed template syntax.
TemplateSyntaxErrorat load time, usually introduced by a half-finished edit../manage.py checkdoesn't crawl templates.
What it deliberately does not do¶
Context-variable resolution. A template's {{ foo.bar }} can only be
judged against a specific view's context, and wiring that plumbing is a
can of worms that belongs in a views + coverage integration — not here.
Example finding¶
templates — 2 finding(s)
┌─────────┬─────────────────────┬───────────────────────────────┬────────────────────────────────────────────────────────┐
│ Sev │ Rule │ Location │ Message │
├─────────┼─────────────────────┼───────────────────────────────┼────────────────────────────────────────────────────────┤
│ ERROR │ templates.url.unknown│ apps/core/templates/nav.html:12 │ {% url 'mandat-detail' %} — no URL pattern registered │
│ │ │ │ under this name. │
│ │ │ │ → Check for a typo, missing include(), or an app whose │
│ │ │ │ urls.py isn't wired in ROOT_URLCONF. │
│ WARNING │ templates.static.missing│ apps/core/templates/base.html:4 │ {% static 'img/logo-xx.svg' %} — no staticfiles finder │
│ │ │ │ resolves this path. │
└─────────┴─────────────────────┴───────────────────────────────┴────────────────────────────────────────────────────────┘
Configuration¶
[tool.django-doctor.templates]
# Glob patterns of template paths (relative to the template root) to skip.
skip = ["vendor/*", "partials/_debug.html"]
# Set to false if your project doesn't use Django's staticfiles finders.
check_static = true
Scope¶
- Templates under each first-party app's
templates/directory. - Templates under
TEMPLATES[...]["DIRS"]entries that live insidesettings.BASE_DIR— third-party template dirs are skipped. - Namespaced URL names (
foo:bar) are matched both as-is and against the bare tail, so{% url 'mandat:detail' %}resolves when onlydetailis registered.