View API
All 40self. methods you call on self inside a LiveView.
These are the methods you call on self inside a LiveView to drive the page: stream content, track presence, accept uploads, manage forms, flash messages, push to the client, run background work, and navigate. Most become available once you mix in the matching capability (see the Mixins tab).
Streaming
Append, replace, and stream into the DOMPush incremental updates into the page from a handler. The stream() family manages large collections with insert/delete/prune ops instead of full re-renders; stream_text() / stream_to() stream content (like LLM tokens) into a dj-stream target at ~60fps.
self.stream()
Initialise a stream with a collection of items. stream(name, items, dom_id=None, at=-1, reset=False, limit=None)
Signature
stream(name, items, dom_id=None, at=-1, reset=False, limit=None)
Returns
Stream
Sets up an efficient server-side stream; rows are emitted as insert ops instead of re-rendering the whole list, and cleared from server memory after render. at=-1 appends, at=0 prepends. Pairs with a dj-stream container. dom_id is a callable that derives each row's DOM id — if omitted, djust falls back to item.id, then item.pk, then id(item).
def mount(self, request, **kwargs):
self.stream('messages', Message.objects.all()[:50])
self.stream_insert()
Insert one item into a stream. stream_insert(name, item, at=-1)
Signature
stream_insert(name, item, at=-1)
Returns
None
Adds a single item to an initialised stream. at=-1 appends (default), at=0 prepends. The item's id/pk becomes the DOM element id.
@event_handler()
def add_message(self, text: str = "", **kwargs):
msg = Message.objects.create(content=text)
self.stream_insert('messages', msg)
self.stream_delete()
Remove an item from a stream by item or id. stream_delete(name, item_or_id)
Signature
stream_delete(name, item_or_id)
Returns
None
Deletes a row from an initialised stream. Pass the item object or its id; the DOM id is derived from the stream name and item id/pk.
@event_handler()
def delete_message(self, msg_id: int = 0, **kwargs):
Message.objects.filter(pk=msg_id).delete()
self.stream_delete('messages', msg_id)
self.stream_reset()
Clear a stream, optionally repopulating it. stream_reset(name, items=None)
Signature
stream_reset(name, items=None)
Returns
None
Clears all of a stream's DOM children. If items is given, the stream is repopulated after clearing.
@event_handler()
def refresh(self, **kwargs):
self.stream_reset('messages', items=Message.objects.all()[:50])
self.stream_prune()
Cap the number of DOM elements in a stream. stream_prune(name, limit, edge='top')
Signature
stream_prune(name, limit, edge='top')
Returns
None
Trims a stream to at most `limit` elements. edge='top' removes from the start, 'bottom' from the end. Used for infinite scroll to keep the DOM bounded.
@event_handler()
def load_more(self, **kwargs):
self.stream('messages', next_batch, at=-1)
self.stream_prune('messages', limit=100, edge='top')
await self.stream_to()
Send a streaming partial update to the client. async stream_to(stream_name, target=None, html=None)
Signature
async stream_to(stream_name, target=None, html=None)
Returns
None
Batched (~60fps) streaming update over the WebSocket. If html is given it is sent directly, else the target is re-rendered from context. target defaults to [dj-stream='name'].
@event_handler()
async def stream_response(self, prompt: str = "", **kwargs):
async for token in llm_stream(prompt):
self.output += token
await self.stream_to('output')
await self.stream_text()
Stream raw text into a target element. async stream_text(name, text, mode='append', target=None)
Signature
async stream_text(name, text, mode='append', target=None)
Returns
None
Appends (or replaces / prepends) text into the stream target. target defaults to [dj-stream='name']. The workhorse for LLM token streaming.
async def stream_response(self, **kwargs):
async for chunk in fetch_stream():
await self.stream_text('output', chunk)
await self.stream_start()
Signal the start of a stream to the client. async stream_start(name, target=None)
Signature
async stream_start(name, target=None)
Returns
None
Fires a 'start' op — useful to show a spinner before tokens arrive. target defaults to [dj-stream='name'].
await self.stream_start('output')
self.streaming = True
await self.stream_done()
Signal the end of a stream to the client. async stream_done(name, target=None)
Signature
async stream_done(name, target=None)
Returns
None
Fires a 'done' op — useful to clear the loading state once streaming finishes.
await self.stream_done('output')
self.streaming = False
await self.stream_error()
Send an error state to a stream target. async stream_error(name, error, target=None)
Signature
async stream_error(name, error, target=None)
Returns
None
Fires an 'error' op while preserving partial content, so a failure is surfaced without wiping what was already streamed.
try:
await self.stream_to('output')
except Exception as e:
await self.stream_error('output', str(e))
Presence
Who's online + collaborative cursorsTrack who is viewing and what they're doing. track_presence() registers the user with optional metadata; list_presences() and presence_count() read the group; broadcast_to_presence() messages everyone; get_cursors() (with LiveCursorMixin) powers collaborative cursors.
self.track_presence()
Register this user in the presence group. track_presence(meta=None)
Signature
track_presence(meta=None)
Returns
None
Registers the user in the presence group identified by presence_key, with an optional meta dict (name, color, avatar…). No-op during HTTP prerender — only registers under WebSocket. Requires PresenceMixin.
def mount(self, request, **kwargs):
self.track_presence(meta={'name': request.user.username})
self.untrack_presence()
Remove this user from presence tracking. untrack_presence()
Signature
untrack_presence()
Returns
None
Removes the user from the presence group. Called automatically on disconnect; call manually to leave a room without disconnecting.
@event_handler()
def leave_room(self, **kwargs):
self.untrack_presence()
self.list_presences()
List the active presences in the group. list_presences()
Signature
list_presences()
Returns
list[dict]
Returns the active presence records (each a dict of the meta passed to track_presence). Empty if presence_key isn't set or the backend is unavailable.
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
ctx['presences'] = self.list_presences()
return ctx
self.presence_count()
Count the active users in the group. presence_count()
Signature
presence_count()
Returns
int
Imperative count of active presences. For templates prefer the auto-maintained {{ online_count }} attribute over calling this directly.
ctx['online'] = self.presence_count()
self.broadcast_to_presence()
Broadcast an event to everyone in the group. broadcast_to_presence(event, payload=None)
Signature
broadcast_to_presence(event, payload=None)
Returns
None
Sends a named event to all active sessions in the presence group; the payload dict is delivered as kwargs to handlers listening for that event.
@event_handler()
def announce(self, message: str = "", **kwargs):
self.broadcast_to_presence('announcement', {'message': message})
self.get_cursors()
Get live cursor positions (collaborative). get_cursors()
Signature
get_cursors()
Returns
dict
Returns user_id -> cursor data (x, y, timestamp, meta), with stale cursors filtered. Only available on LiveCursorMixin.
ctx['cursors'] = self.get_cursors()
Uploads
Configure slots and consume filesConfigure and consume file uploads server-side. Declare a slot with allow_upload() in mount() (it sets accept/multiple automatically), then read completed files with consume_uploaded_entries() in the handler that saves them.
self.allow_upload()
Configure a named file-upload slot. allow_upload(name, accept='', max_entries=1, max_file_size=10_000_000, resumable=False)
Signature
allow_upload(name, accept='', max_entries=1, max_file_size=10_000_000, resumable=False)
Returns
UploadConfig
Declares an upload slot referenced as dj-upload='name'. accept filters extensions/MIME types; the input's accept/multiple attrs are set automatically. resumable=True survives WS reconnects. Requires UploadMixin.
def mount(self, request, **kwargs):
self.allow_upload('avatar', accept='.jpg,.png', max_file_size=5_000_000)
self.consume_uploaded_entries()
Iterate completed uploads, cleaning up after. consume_uploaded_entries(name)
Signature
consume_uploaded_entries(name)
Returns
generator[UploadEntry]
Yields UploadEntry objects (client_name, client_size, file, data) for completed uploads, cleaning up temp files after iteration. Call from the handler that saves the files.
@event_handler()
def save_avatar(self, **kwargs):
for entry in self.consume_uploaded_entries('avatar'):
default_storage.save(entry.client_name, entry.file)
Forms
Bind, validate, and read form fieldsWork with a bound Django form inside a LiveView. Read live values and validation state with get_field_value() / get_field_errors() / has_field_errors(); reach the form object via form_instance; clear everything with reset_form(). Requires FormMixin.
self.reset_form()
Reset a bound form to its initial state. reset_form()
Signature
reset_form()
Returns
None
Clears form_data, field_errors and form_errors and resets validity. Requires FormMixin.
@event_handler()
def clear(self, **kwargs):
self.reset_form()
self.form_instance
The live Django form instance (re-hydrated). form_instance (property)
Signature
form_instance (property)
Returns
forms.Form
Returns the bound Django form, re-creating it from serialized state when needed. Requires FormMixin.
field = self.form_instance.fields.get('email')
self.get_field_value()
Get the current value of a form field. get_field_value(field_name, default='')
Signature
get_field_value(field_name, default='')
Returns
Any
Returns form_data[field_name] or the default. Requires FormMixin.
email = self.get_field_value('email')
self.get_field_errors()
Get the validation errors for a field. get_field_errors(field_name)
Signature
get_field_errors(field_name)
Returns
list[str]
Returns the field's error messages, or an empty list. Requires FormMixin.
errors = self.get_field_errors('email')
self.has_field_errors()
Check whether a field has errors. has_field_errors(field_name)
Signature
has_field_errors(field_name)
Returns
bool
True if the field currently has validation errors. Requires FormMixin.
{% if has_field_errors('email') %}
<span class="error">Invalid email</span>
{% endif %}
Flash & push
Notifications, page metadata, client pushesTalk to the client outside the normal render. put_flash() queues a notification; page_title / page_meta update the document head via a side-channel; push_event() / push_commands() / trigger_submit() send events, JS command chains, and native form submits to the browser.
self.put_flash()
Queue a transient flash message. put_flash(level, message)
Signature
put_flash(level, message)
Returns
None
Queues a notification; level ('success','error','info'…) becomes the CSS class dj-flash-{level}. Flushed to the client after the response. Requires FlashMixin (auto-included).
@event_handler()
def save(self, **kwargs):
self.put_flash('success', 'Saved!')
self.clear_flash()
Clear queued flash messages. clear_flash(level=None)
Signature
clear_flash(level=None)
Returns
None
Clears all flash messages, or only those of a given level.
self.clear_flash('error')
self.push_event()
Push a custom event to client JS hooks. push_event(event, payload=None)
Signature
push_event(event, payload=None)
Returns
None
Dispatches to dj-hook handlers and as a CustomEvent on document; the payload dict becomes event.detail. Use for client-only side effects after a handler.
self.push_event('confetti', {'count': 50})
self.push_commands()
Push a JS command chain to run on the client. push_commands(chain)
Signature
push_commands(chain)
Returns
None
Runs a djust.js.JSChain on the client for DOM automation (show/hide/add_class/focus/dispatch) with no client hook needed.
from djust.js import JS
self.push_commands(
JS.add_class('highlight', to='#btn').focus('#btn')
)
self.trigger_submit()
Trigger a native form POST on the client. trigger_submit(selector)
Signature
trigger_submit(selector)
Returns
None
After the handler, the client calls .submit() on the matching form (which must carry dj-trigger-action). Used for OAuth or payment handoffs that need a real navigation.
@event_handler()
def checkout(self, **kwargs):
self.trigger_submit('#payment-form')
self.page_title
Update the document title (no re-render). page_title (property)
Signature
page_title (property)
Returns
str
Assigning page_title queues a title update over a side-channel — no VDOM diff required. Requires PageMetadataMixin (auto-included).
self.page_title = f'Chat ({self.unread} unread)'
self.page_meta
Update <meta> tags dynamically. page_meta (property)
Signature
page_meta (property)
Returns
dict
Assigning a dict of name->content queues meta-tag updates (one command per key). Useful for OpenGraph/SEO on a reactive page.
self.page_meta = {'og:title': 'My Article'}
Async work
Run work off the request, then re-renderRun work off the request cycle. start_async() schedules a callback to run after the current state flushes (re-rendering when it finishes); cancel_async() stops it; defer() runs a one-shot callback after render/patch completes — good for telemetry and cleanup.
self.start_async()
Run a callback in the background after flushing. start_async(callback, *args, name=None, **kwargs)
Signature
start_async(callback, *args, name=None, **kwargs)
Returns
None
Schedules work to run after the current state flushes to the client, then re-renders on completion. Name tasks to run several concurrently. Requires AsyncWorkMixin (auto-included).
@event_handler()
def generate(self, **kwargs):
self.generating = True
self.start_async(self._do_generate, name='gen')
def _do_generate(self):
self.output = expensive_call()
self.generating = False
self.cancel_async()
Cancel a background task by name. cancel_async(name)
Signature
cancel_async(name)
Returns
None
Cancels a scheduled task; if it's already running, its completion re-render is skipped.
@event_handler()
def cancel(self, **kwargs):
self.cancel_async('gen')
self.generating = False
self.defer()
Run a callback once after render + patch. defer(callback, *args, **kwargs)
Signature
defer(callback, *args, **kwargs)
Returns
None
Queues a sync callback to run after the render/patch cycle (no further re-render). Good for telemetry or cleanup that shouldn't block the response.
@event_handler()
def track(self, **kwargs):
self.count += 1
self.defer(self._record_metric)
Wizard
Step through a multi-step formStep through a multi-step form. next_step() / prev_step() / go_to_step() navigate with per-step validation; submit_wizard() re-validates every step before calling on_wizard_complete(). Requires WizardMixin.
self.go_to_step()
Jump to a completed wizard step. go_to_step(step_index=0)
Signature
go_to_step(step_index=0)
Returns
None
Navigates to a previously-completed step for editing, skipping validation on the jump. Requires WizardMixin.
@event_handler()
def edit_step(self, step_index: int = 0, **kwargs):
self.go_to_step(step_index=step_index)
self.next_step()
Validate and advance to the next step. next_step()
Signature
next_step()
Returns
None
Validates the current step, marks it complete, and advances. Stops at the last step. Requires WizardMixin.
<button dj-click="next_step">Next</button>
self.prev_step()
Go back one wizard step. prev_step()
Signature
prev_step()
Returns
None
Returns to the previous step without validation. Stops at the first step. Requires WizardMixin.
<button dj-click="prev_step">Back</button>
self.submit_wizard()
Validate all steps and finish the wizard. submit_wizard()
Signature
submit_wizard()
Returns
None
Re-validates every step (guarding against tampering) and calls on_wizard_complete(step_data) when all pass. Requires WizardMixin.
def on_wizard_complete(self, step_data):
Claim.objects.create(**step_data['personal'])