{{ post.title }}
{{ post.content }}
* Home :PROPERTIES: :ONE: one-custom-default-home :CUSTOM_ID: / :TITLE: :DESCRIPTION: Build real-time, reactive interfaces with Django using WebSockets: write Python, not JavaScript. :NAVIGATOR-ACTIVE: home :END: ** Build real-time SPAs with Python, not JavaScript Django LiveView is a framework for creating real-time, interactive web applications entirely in Python, inspired by [[https://hexdocs.pm/phoenix_live_view/][Phoenix LiveView]] and [[https://laravel-livewire.com/][Laravel Livewire]]. It is built on top of Django Channels. Build rich, dynamic user experiences with server-rendered HTML without writing a single line of JavaScript. Perfect for Django developers who want real-time features without the complexity of a separate frontend framework. ** See it in action Here's a complete example: a button that loads the latest blog article with a single click. *HTML:* #+BEGIN_SRC html
#+END_SRC *Python:* #+BEGIN_SRC python from liveview import liveview_handler, send from django.template.loader import render_to_string @liveview_handler("load_latest_article") def load_latest_article(consumer, content): # Get the latest article from database article = Article.objects.latest('published_at') # Render with Django templates html = render_to_string('article.html', { 'article': article }) # Send to frontend send(consumer, { "target": "#article-container", "html": html }) #+END_SRC *Result (after clicking the button):* #+BEGIN_SRC htmlDjango Channels extends Django to handle WebSockets, long-running connections, and background tasks...
Read moreHello, World!
" }) #+END_SRC HTML code: #+BEGIN_SRC htmlHello, {name}! Welcome to Django LiveView.
" }) #+END_SRC HTML code: #+BEGIN_SRC html{{ user.bio }}
{% if is_online %} Online {% endif %}{{ post.content }}
You have a new message
Loading more...
You must be logged in
" }) return False # Cancel handler execution return True # Continue to handler def logging_middleware(consumer, content, function_name): """Log all handler calls""" import logging logger = logging.getLogger(__name__) user = consumer.scope.get("user") logger.info(f"Handler '{function_name}' called by {user}") return True # Continue to handler # Register middleware liveview_registry.add_middleware(auth_middleware) liveview_registry.add_middleware(logging_middleware) #+END_SRC *** Data Handling ** Script Execution Execute JavaScript code directly from your Python handlers. ⚠️ *Security Warning:* Only execute scripts from trusted sources. Never pass user input directly to the ~script~ parameter without sanitization, as this can lead to XSS (Cross-Site Scripting) vulnerabilities. *** Basic Script Execution #+BEGIN_SRC python from liveview import liveview_handler, send @liveview_handler("show_notification") def show_notification(consumer, content): message = content["form"]["message"] # Execute JavaScript to show a browser notification send(consumer, { "script": f""" if (Notification.permission === 'granted') {{ new Notification('New Message', {{ body: '{message}', icon: '/static/icon.png' }}); }} """ }) #+END_SRC *** Combining HTML and Script You can combine HTML updates with script execution: #+BEGIN_SRC python @liveview_handler("load_chart") def load_chart(consumer, content): import json chart_data = json.dumps(get_chart_data()) # Update HTML html = render_to_string("chart_container.html", { "chart_id": "sales-chart" }) send(consumer, { "target": "#chart-container", "html": html }) # Initialize chart with JavaScript send(consumer, { "script": f""" const ctx = document.getElementById('sales-chart'); new Chart(ctx, {{ type: 'bar', data: {chart_data} }}); """ }) #+END_SRC *** Inline Scripts in HTML Django LiveView automatically extracts and executes ~ ''' send(consumer, { "target": "#component-container", "html": html }) #+END_SRC The script will be automatically extracted and executed after the HTML is rendered. *** Use Cases - Integrating third-party JavaScript libraries (charts, maps, etc.) - Triggering browser APIs (notifications, geolocation, etc.) - Initializing complex UI components - Playing sounds or animations - Focusing specific elements with custom logic *** Best Practices 1. ✓ Sanitize any user input before including in scripts 2. ✓ Use JSON serialization for data: ~import json; json.dumps(data)~ 3. ✓ Prefer ~ #+END_SRC *** File Size Limitations WebSocket has practical limits for Base64-encoded files: - ✓ *Small files* (< 1MB): Images, documents, avatars - ⚠️ *Medium files* (1-5MB): May work but can be slow - ✗ *Large files* (> 5MB): Not recommended, use traditional HTTP upload For large files, use a traditional HTTP POST to upload, then notify via WebSocket. *** Security Considerations 1. ✓ Validate file types (check magic bytes, not just extensions) 2. ✓ Limit file sizes on the server 3. ✓ Scan files for malware if accepting from untrusted users 4. ✓ Store files outside the web root 5. ✓ Use unique filenames to prevent overwrites 6. ✓ Validate image dimensions and format with Pillow/PIL ** Message Queue System Django LiveView automatically queues messages when the WebSocket connection is not ready. *** How It Works When you call a LiveView handler but the WebSocket is: - Still connecting - Temporarily disconnected - Reconnecting after a network failure The message is automatically queued and sent once the connection is restored. #+BEGIN_SRC html #+END_SRC If the user clicks "Save Draft" while offline, the message is queued. When the connection is restored, all queued messages are sent automatically in order. *** User Feedback During Queueing Show users when their actions are being queued: #+BEGIN_SRC html #+END_SRC ** Network Connectivity Handling Django LiveView automatically handles network connectivity changes. *** Automatic Detection The framework detects when: - Network goes offline (airplane mode, WiFi disconnect, etc.) - Network comes back online - Connection to the server is lost - Connection to the server is restored *** Visual Feedback Create a connection status modal that appears when connectivity is lost: #+BEGIN_SRC html {% load static %} {% load liveview %}Dynamic handler executed!
" }) # Register manually handler_name = "dynamic_action" decorated_func = liveview_registry.register(handler_name)(dynamic_handler) # Now callable from frontend #
This is a comment