Under the Hood Of the Fastest LiveView.
Explore the architecture that makes djust the fastest Python LiveView framework.
01. Rust VDOM Engine
Traditional Django templates re-render the entire string for every request. djust compiles templates into a Virtual DOM tree in Rust.
-
Sub-millisecond Patching Diffing happens in ~0.8ms, compared to 25ms+ for Django template rendering.
-
Smart Diffing We track variable dependencies. If you only change
{{ count }}, we only check that node.
Rendering Performance (100 items)
{% extends "base.html" %} {% block title %}Dashboard{% endblock %} {% block content %} <div class="stats"> <h1>Welcome, {{ user.name }}</h1> <!-- This updates independently --> <div>Active Users: {{ active_count }}</div> <!-- Loop updates are optimized --> {% for item in items %} <div>{{ item.name }}</div> {% endfor %} </div> {% endblock %}
02. Unified Templates
Don't learn a new syntax. djust supports standard Django template inheritance.
The entire page—base template, child template, and included components—is compiled into a single VDOM tree. This means you can update a variable in the navbar (defined in `base.html`) from a view rendering `child.html`.
How it works:
- Parser resolves
{% extends %}and merges blocks. - Merged template is compiled to Rust VDOM.
- State changes trigger a diff of the entire tree.
- Patches are sent for any changed node, anywhere in the tree.
03. ORM JIT Compiler
The #1 performance killer in Django apps is the N+1 query problem. djust solves it automatically.
Our compiler analyzes your templates to see exactly which fields you use (e.g.,
{{ book.author.name }}). It then automatically injects the optimal
select_related and prefetch_related calls into your QuerySet.
-
Zero N+1 Queries Forgot
select_related? No problem. We fix it for you. -
Zero Data Leaks If a field isn't in the HTML, it's never fetched from the DB.
{% for book in books %}
{{ book.author.name }}
{% endfor %}
{% for book in books %}
{{ book.author.name }}
{% endfor %}
JOIN authors ON ...
04. Python-First State Management
Complex UI patterns usually require JavaScript. djust provides Python decorators that handle them for you.
Search & Autocomplete
Automatically delays the server request until the user stops typing. No more flooding your database with partial queries.
@debounce(0.5) def search(self, query): self.results = DB.search(query)
Instant Feedback
Updates the UI immediately in the browser, then validates on the server. If the server rejects it, the UI rolls back automatically.
@optimistic def toggle_like(self): self.liked = not self.liked
Component Sync
Synchronize state between multiple components purely on the client-side, without a server roundtrip.
@client_state(['tab']) def set_tab(self, tab): self.tab = tab
05. Security by Default
WebSocket-based frameworks open new attack surfaces. djust locks them down out of the box so you don't have to think about it.
-
WebSocket Event Hardening Three-layer defense: event name guard,
@event_handlerallowlist, and server-side rate limiting. -
Built-in Security Utilities
safe_setattr()blocks prototype pollution,sanitize_for_log()prevents log injection, DEBUG-aware error handling. -
Per-IP Connection Limits Prevents resource exhaustion from a single client opening hundreds of WebSocket connections.
06. Real-Time Streaming
Stream data to the browser as it generates. Perfect for LLM responses, live logs, and progress indicators — no polling required.
-
Token-by-Token Output Stream LLM responses, logs, or any async data directly to the browser as it generates.
-
Multiple Stream Targets Use
stream_to()to push updates to different DOM elements simultaneously.
from djust import LiveView
from djust.streaming import StreamingMixin
class ChatView(StreamingMixin, LiveView):
template_name = 'chat.html'
async def ask_ai(self, prompt):
self.stream_start('response')
async for token in llm.stream(prompt):
self.stream_text('response', token)
self.stream_done('response')
from djust import LiveView
from djust.presence import PresenceMixin
class DocView(PresenceMixin, LiveView):
template_name = 'doc.html'
def on_presence_join(self, user):
self.online_users = self.get_presences()
def on_presence_leave(self, user):
self.online_users = self.get_presences()
07. Live Collaboration & Presence
Build collaborative features without third-party services. Know who's online, track cursors, and broadcast changes — all built in.
-
Who's Online Built-in presence tracking shows connected users in real-time with automatic join/leave detection.
-
Live Cursors
LiveCursorMixinbroadcasts cursor positions for Google Docs-style collaboration.
08. Server Push
Push updates from anywhere in your backend — Celery tasks, management commands, webhooks — directly to the browser without the user lifting a finger.
-
Background to Browser Push state updates from Celery tasks, management commands, or any background process directly to connected clients.
-
Async Support Use
apush_to_view()in async contexts for non-blocking push operations.
from djust import push_to_view
# From a Celery task
@app.task
def process_upload(view_id, file_id):
result = heavy_processing(file_id)
push_to_view(view_id, {
'progress': 100,
'result': result,
})
<div dj-hook="Chart">
<canvas id="myChart"></canvas>
</div>
<script>
djust.hooks.Chart = {
mounted() {
this.chart = new Chart(this.el, data);
},
updated() {
this.chart.update();
}
};
</script>
09. JavaScript Hooks
When you need client-side power, hooks give you full lifecycle control over DOM elements without leaving the djust ecosystem.
-
Full Lifecycle Control
mounted,updated,destroyed,disconnected,reconnectedcallbacks for DOM elements. -
Push Events Hooks can push events back to the server and receive events from it via
pushEvent()andhandleEvent().
10. Two-Way Data Binding
Bind form inputs to server state with a single attribute. No JavaScript event handlers, no manual serialization — just dj-model.
-
Automatic Sync
dj-modelbinds form inputs to server state. Changes propagate instantly without writing event handlers. -
Smart Modifiers Use
.lazyfor on-blur updates or.debounce-300for throttled typing — one attribute, zero boilerplate.
<form>
<input dj-model="name"
placeholder="Your name">
<textarea dj-model.lazy="bio">
</textarea>
<input dj-model.debounce-300="search"
placeholder="Search...">
<p>Hello, {{ name }}!</p>
</form>