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-SideBasic reactivity with server-side state management
Each click executes increment() Python method on server
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}
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-SideFull create, read, update, delete operations
Add, toggle, delete → all Python methods on server
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 }
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-SideInstant feedback with Django Forms integration
Validation runs validate_field() on every keystroke
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
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
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-SideInteractive 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
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
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.