v1.2.0
djust 1.2 makes the Rust template engine behave like Django's, turns components into view state, and fixes eleven security advisories. djust 1.1.4, released the same day, carries the same security fixes for the 1.1 line.
Read the full release notes before upgrading: djust 1.2 release notes. They cover every incompatible change, what to do about each one, and an upgrade checklist.
Supports Python 3.10 to 3.14 and Django 4.2 (4.2.29 or later) to 5.2, the same range as 1.1.
Highlights
- Django template compatibility. All 25 built-in tags and 57 built-in filters,
{% load %}for your own tag libraries,{% translate %}/{% blocktranslate %}, and dotted lookups against the live Python object. 1032 of the 1047 Djangotemplate_teststhat reach an engine pass (98.57%). - Faster renders with large state. Render cost now depends on what the template reads, not on everything the view holds.
- Components are state. Class-level components bind per view and handle their own events (ADR-031). An event that changes one component patches only that component (ADR-032). Writing
self.rating.value = 5re-renders and survives a reconnect (ADR-033). - Component catalogue at
/theme/components/, backed bydescribe_component(). djust initadds djust to an existing Django project.djust newgenerates a themed starter page.- Update and security notices from the CLI, the dev server and
manage.py check(djust.U001). @debounce/@throttlein the client,dj-mouseenter/dj-mouseleave,AudioMixin,LiveComponentTestClient, anddjust replayfor bug captures.
Backwards incompatible changes
Security hardening:
- Built-in components HTML-escape their content. Mark slot HTML safe with
mark_safe()orformat_html(). - djust admin enforces Django model permissions. Staff users who aren't superusers need
view_/add_/change_/delete_permissions. - The observability endpoints require the
X-Djust-Observability-Tokenheader.djust_mcpsends it;manage.py djust_observability_tokenprints it. - A custom tag that returns a plain string has its output escaped, and so does a custom filter registered with
is_safe=Truewhen its input wasn't safe. Returnformat_html()ormark_safe()for markup. DataTablesorts, filters and groups only on declared columns. Filtering needs"filterable": True.- A LiveView joins its channel groups only after its permission checks pass.
- Sticky
{% live_render %}children are re-authorized on every parent render. - State snapshots from 1.1 are rejected once.
- In-flight resumable uploads restart.
- Theme cookies naming an unknown pack or layout fall back to the defaults.
Templates:
- The errors Django raises are now raised too, many when the template is loaded: unknown filters and tags,
_-prefixed names, wrong filter argument counts, and{% for %}over a non-iterable. {% url %}raisesNoReverseMatch; useas varwhere a failed reverse is expected.- Values render as in Django: datetimes in the current time zone, localized numbers, and
True/None/[1, 2]. SetLIVEVIEW_CONFIG["django_value_repr"] = Falseto keep 1.1's rendering of plain values.
Runtime and client:
- In-place mutations re-render.
- A
list[Model]isn't re-queried on every event. - The tick loop honours
_skip_render. - URL kwargs arrive decoded.
- Booleans reach the browser as
true/false,Decimalvalues as strings, and datetimes inDjangoJSONEncoderformat.
Components and theming:
self.navis aBoundComponent; read its state fromself.nav.state.TableComponent.sort_by(column=...)andTabsComponent.activate_tab(tab=...)changed their arguments.- The modal backdrop is a
.dj-scrimelement. - The theme gallery moved to
/theme/themes/and the storybook to/theme/components/. The old paths redirect.Storybook*names becameComponents*.
Testing:
LiveViewTestClient.mount()takes the WebSocket branch by default; passvia_websocket=Falsefor the prerender.send_event()raisesNoHandlerFoundErrorfor an unknown handler.
Checks:
- New
T018,C016,V014andU001messages. C013fires until you runcollectstatic.
Removed:
LIVEVIEW_CONFIG["template_resolve_lazy"]is gone.- The unused static files
djust/security.js,djust/decorators.jsanddjust/js/pwa.jsare no longer shipped.
Security
1.2.0 and 1.1.4 fix these advisories:
- GHSA-fccp-5h88-g34j (DataTable)
- GHSA-jv2m-fcq9-94xf (admin_ext)
- GHSA-c44q-w252-mr67 (observability)
- GHSA-hc2m-gvfj-x6r3 and GHSA-r372-rrpw-5cgj (components)
- GHSA-j23m-jxwp-m3vq (theming)
- GHSA-6q7c-hvpc-ff2q (presence)
- GHSA-5ffg-p52h-v2ph (state snapshots)
- GHSA-74vj-mpp4-45cg (sticky live_render)
- GHSA-7fcf-23mf-rhhm (uploads)
- GHSA-p9vp-rh5f-2cvq (template filters; fixed in 1.2.0rc2)
GHSA-3hp5-hxf8-qc48 (HTTP POST authorization) was fixed earlier, in 1.2.0rc8 and 1.1.3.
Upgrading from 1.1
pip install "djust==1.2.0", then runpython manage.py collectstatic.- Run
python manage.py check. Handle the new T018, C016, V014 and U001 messages. For templates that use{% extends %}, also runmanage.py djust_typecheck. - Run your tests. Add
via_websocket=Falseto prerender tests, and expectNoHandlerFoundErrorfor events that have no handler. - Load every template once. djust now raises template errors that 1.1 ignored.
- Check rendered timestamps, numbers,
{{ }}output and{% url %}calls. - Mark component slot HTML safe, and make custom tags and filters that produce markup return safe strings.
- Grant model permissions to djust admin staff, and add
"filterable": Trueto theDataTablecolumns you filter on. - Update client JavaScript and CSS that reads booleans, decimals or datetimes, or targets the modal backdrop,
data-valueordata-row-id. - Update links and imports for the theme gallery and component catalogue.
Full notes: docs/website/releases/1.2.md. Every change since 1.1: CHANGELOG, sections 1.2.0rc1 to 1.2.0 (1.2.0 is identical to 1.2.0rc11 apart from the version).
Every pull request since 1.1: compare v1.1.3...v1.2.0.