Home Features Security Examples Quick Start
Live Demos

Examples & Demos

Explore real djust applications. Each demo is fully interactive with complete source code.

100% Server-Side Execution

Every click, input, and interaction you see below runs Python code on the server. No client-side JavaScript logic required. It just feels instant thanks to Rust-powered sub-millisecond VDOM diffing.

Real-Time Counter

Server-Side

Basic reactivity with server-side state management

0

Each click executes increment() Python method on server

views.py
 1from djust import LiveView
 2
 3class CounterView(LiveView):
 4    template_name = 'counter.html'
 5
 6    def mount(self, request):
 7        """Initialize counter state"""
 8        self.count = 0
 9
10    def increment(self):
11        """Increment counter by 1"""
12        self.count += 1
13
14    def decrement(self):
15        """Decrement counter by 1"""
16        self.count -= 1
17
18    def reset(self):
19        """Reset counter to 0"""
20        self.count = 0
21
22    def get_context_data(self, **kwargs):
23        return {'count': self.count}
template.html
 1<div class="counter-app">
 2    <h2>Counter Example</h2>
 3
 4    <div class="count-display">
 5        {{ count }}
 6    </div>
 7
 8    <div class="button-group">
 9        <button @click="decrement" class="btn-danger">
10            Decrement
11        </button>
12        <button @click="reset" class="btn-secondary">
13            Reset
14        </button>
15        <button @click="increment" class="btn-success">
16            Increment
17        </button>
18    </div>
19</div>

Todo List (CRUD)

Server-Side

Full create, read, update, delete operations

0 completed 0 total

Add, toggle, delete → all Python methods on server

views.py
 1from djust import LiveView
 2
 3class TodoListView(LiveView):
 4    template_name = 'todo.html'
 5
 6    def mount(self, request):
 7        """Initialize todo list"""
 8        self.todos = []
 9        self.next_id = 1
10
11    def add_todo(self, text: str = "", **kwargs):
12        """Add new todo item"""
13        if text.strip():
14            self.todos.append({
15                'id': self.next_id,
16                'text': text,
17                'completed': False
18            })
19            self.next_id += 1
20
21    def toggle_todo(self, id: int = None, **kwargs):
22        """Toggle todo completion status"""
23        todo = next((t for t in self.todos if t['id'] == id), None)
24        if todo:
25            todo['completed'] = not todo['completed']
26
27    def delete_todo(self, id: int = None, **kwargs):
28        """Delete todo item"""
29        self.todos = [t for t in self.todos if t['id'] != id]
30
31    def get_context_data(self, **kwargs):
32        completed = sum(1 for t in self.todos if t['completed'])
33        return {
34            'todos': self.todos,
35            'completed_count': completed,
36            'total_count': len(self.todos)
37        }
template.html
 1<div class="todo-app">
 2    <h2>Todo List</h2>
 3
 4    <form @submit="add_todo" class="add-form">
 5        <input type="text"
 6               name="text"
 7               placeholder="What needs to be done?" />
 8        <button type="submit">Add</button>
 9    </form>
10
11    <div class="todo-list">
12        {% for todo in todos %}
13        <div class="todo-item">
14            <input type="checkbox"
15                   @change="toggle_todo"
16                   data-id="{{ todo.id }}"
17                   {% if todo.completed %}checked{% endif %} />
18            <span class="{% if todo.completed %}completed{% endif %}">
19                {{ todo.text }}
20            </span>
21            <button @click="delete_todo"
22                    data-id="{{ todo.id }}"
23                    class="delete-btn">
24                Delete
25            </button>
26        </div>
27        {% endfor %}
28    </div>
29
30    <div class="stats">
31        <span>{{ completed_count }} completed</span>
32        <span>{{ total_count }} total</span>
33    </div>
34</div>

Real-Time Form Validation

Server-Side

Instant feedback with Django Forms integration

Real-time validation with instant feedback

Validation runs validate_field() on every keystroke

views.py
 1from djust import LiveView
 2from djust.forms import FormMixin
 3from .forms import SignupForm
 4
 5class SignupView(FormMixin, LiveView):
 6    form_class = SignupForm
 7    template_name = 'signup.html'
 8
 9    def mount(self, request):
10        """Initialize form view"""
11        self.success_message = None
12
13    def validate_field(self, field: str = None, value: str = "", **kwargs):
14        """Real-time field validation"""
15        # Validation happens automatically via FormMixin
16        # Errors are displayed in real-time
17        pass
18
19    def form_valid(self, form):
20        """Handle valid form submission"""
21        # Save the user
22        user = form.save()
23        self.success_message = "Account created successfully!"
24        # Reset form
25        self.form = self.form_class()
26
27    def form_invalid(self, form):
28        """Handle invalid form submission"""
29        # Errors displayed automatically
30        pass
forms.py
 1from django import forms
 2from django.contrib.auth.models import User
 3
 4class SignupForm(forms.ModelForm):
 5    """User signup form with validation"""
 6
 7    password = forms.CharField(
 8        widget=forms.PasswordInput,
 9        min_length=8,
10        help_text="At least 8 characters"
11    )
12
13    class Meta:
14        model = User
15        fields = ['email', 'password']
16
17    def clean_email(self):
18        """Validate email is unique"""
19        email = self.cleaned_data.get('email')
20        if User.objects.filter(email=email).exists():
21            raise forms.ValidationError(
22                "Email already registered"
23            )
24        return email
25
26    def clean_password(self):
27        """Validate password strength"""
28        password = self.cleaned_data.get('password')
29        if len(password) < 8:
30            raise forms.ValidationError(
31                "Password must be at least 8 characters"
32            )
33        return password
template.html
 1<div class="signup-form">
 2    <h2>Sign Up</h2>
 3
 4    <form @submit="submit_form">
 5        <div class="form-field">
 6            <label for="email">Email</label>
 7            <input type="email"
 8                   name="email"
 9                   @change="validate_field"
10                   value="{{ form.email.value|default:'' }}" />
11            {% if form.email.errors %}
12            <p class="error">{{ form.email.errors.0 }}</p>
13            {% endif %}
14        </div>
15
16        <div class="form-field">
17            <label for="password">Password</label>
18            <input type="password"
19                   name="password"
20                   @change="validate_field" />
21            {% if form.password.errors %}
22            <p class="error">{{ form.password.errors.0 }}</p>
23            {% endif %}
24            <p class="help">At least 8 characters</p>
25        </div>
26
27        <button type="submit">Sign Up</button>
28
29        {% if success_message %}
30        <p class="success">✓ {{ success_message }}</p>
31        {% endif %}
32    </form>
33</div>

Sortable Data Table

Server-Side

Interactive table with search and sorting

Name
Price
Stock
27" Monitor $399 12
Laptop Pro $1299 42
Mechanical Keyboard $89 23
USB-C Hub $45 78
Wireless Mouse $29 156

Search & sort execute search() and sort() on server

views.py
 1from djust import LiveView
 2from .models import Product
 3
 4class ProductTableView(LiveView):
 5    template_name = 'product_table.html'
 6
 7    def mount(self, request):
 8        """Initialize table view"""
 9        self._products = Product.objects.all()
10        self.search_query = ""
11        self.sort_by = "name"
12        self.sort_order = "asc"
13
14    def search(self, value: str = "", **kwargs):
15        """Search products by name"""
16        self.search_query = value
17        self._refresh_products()
18
19    def sort(self, field: str = None, **kwargs):
20        """Sort products by field"""
21        if field == self.sort_by:
22            # Toggle order
23            self.sort_order = "desc" if self.sort_order == "asc" else "asc"
24        else:
25            self.sort_by = field
26            self.sort_order = "asc"
27        self._refresh_products()
28
29    def _refresh_products(self):
30        """Refresh product list with filters"""
31        queryset = Product.objects.all()
32
33        # Apply search filter
34        if self.search_query:
35            queryset = queryset.filter(
36                name__icontains=self.search_query
37            )
38
39        # Apply sorting
40        order_prefix = "-" if self.sort_order == "desc" else ""
41        queryset = queryset.order_by(f"{order_prefix}{self.sort_by}")
42
43        self._products = queryset
44
45    def get_context_data(self, **kwargs):
46        self.products = self._products  # JIT serialization
47        context = super().get_context_data(**kwargs)
48        context.update({
49            'search_query': self.search_query,
50            'sort_by': self.sort_by,
51            'sort_order': self.sort_order
52        })
53        return context
template.html
 1<div class="product-table">
 2    <h2>Products</h2>
 3
 4    <input type="text"
 5           @input="search"
 6           value="{{ search_query }}"
 7           placeholder="Search products..." />
 8
 9    <table>
10        <thead>
11            <tr>
12                <th @click="sort" data-field="name">
13                    Name
14                    {% if sort_by == 'name' %}
15                        {% if sort_order == 'asc' %}↑{% else %}↓{% endif %}
16                    {% endif %}
17                </th>
18                <th @click="sort" data-field="price">
19                    Price
20                    {% if sort_by == 'price' %}
21                        {% if sort_order == 'asc' %}↑{% else %}↓{% endif %}
22                    {% endif %}
23                </th>
24                <th @click="sort" data-field="stock">
25                    Stock
26                    {% if sort_by == 'stock' %}
27                        {% if sort_order == 'asc' %}↑{% else %}↓{% endif %}
28                    {% endif %}
29                </th>
30            </tr>
31        </thead>
32        <tbody>
33            {% for product in products %}
34            <tr>
35                <td>{{ product.name }}</td>
36                <td>${{ product.price }}</td>
37                <td>{{ product.stock }}</td>
38            </tr>
39            {% endfor %}
40        </tbody>
41    </table>
42</div>

Ready to Build Your Own?

Try these examples in the interactive playground or install djust locally to start building real-time applications.