Tutorial | Django LiveView

Welcome to the quick start. Here you will learn how to create your first real-time SPA using Django LiveView. I assume you have a basic understanding of Django and Python.

This guide provides two paths: a quick one without Redis for immediate testing, and a production-ready path with Redis.

Step 0: Prerequisites

Before starting, ensure you have:

  • Python 3.10 or higher

  • Django 4.2 or higher

  • A Django project created (if not: django-admin startproject myproject)

  • A Django app created (if not: python manage.py startapp app)

Step 1: Installation

Option A: Quick start (without Redis)

For testing purposes only. Not suitable for production.

pip install django-liveview channels daphne

Option B: Production ready (with Redis)

Recommended for development and production environments.

pip install django-liveview channels channels-redis daphne redis

You'll also need Redis running:

  • Linux/Mac: redis-server

  • Docker: docker run -d -p 6379:6379 redis:alpine

  • Windows: Use Docker or WSL

Step 2: Configure Django

Add to your settings.py:

# settings.py
INSTALLED_APPS = [
    "daphne",  # Must be first for ASGI support
    "channels",
    "liveview",
    "app",  # Your app
    # ... other Django apps
]

# ASGI configuration
ASGI_APPLICATION = "myproject.asgi.application"

Channel Layer Configuration

Choose one option:

Option A: Without Redis (testing only)

# settings.py
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels.layers.InMemoryChannelLayer"
    }
}

Limitations: Only works with runserver, not cross-process, not production-ready.

Option B: With Redis (recommended)

# settings.py
CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels_redis.core.RedisChannelLayer",
        "CONFIG": {
            "hosts": [("127.0.0.1", 6379)],
        },
    },
}

Step 3: Setup ASGI routing

Create or update myproject/asgi.py:

# myproject/asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from channels.security.websocket import AllowedHostsOriginValidator
from liveview.routing import get_liveview_urlpatterns

os.environ.setdefault("DJANGO_SETTINGS_MODULE", "myproject.settings")

application = ProtocolTypeRouter({
    "http": get_asgi_application(),
    "websocket": AllowedHostsOriginValidator(
        AuthMiddlewareStack(
            URLRouter(
                get_liveview_urlpatterns()
            )
        )
    ),
})

Step 4: Add JavaScript to your base template

Create app/templates/base.html:

<!-- app/templates/base.html -->
{% load static %}
{% load liveview %}
<!DOCTYPE html>
<html lang="en" data-room="{% liveview_room_uuid %}">
<head>
    <meta charset="UTF-8">
    <title>{% block title %}My Site{% endblock %}</title>
</head>
<body data-controller="page">
    {% block content %}{% endblock %}

    <!-- Django LiveView JavaScript -->
    <script src="{% static 'liveview/liveview.min.js' %}" defer></script>
</body>
</html>

Important attributes:

  • data-room="{% liveview_room_uuid %}" on <html>: unique room ID for each page load

  • data-controller="page" on <body>: activates the Stimulus controller

Note: Templates are placed in app/templates/ to follow Django's app-based template discovery with APP_DIRS = True.

Step 5: Create your first LiveView handler

Create the directory structure:

mkdir -p app/liveview_components
touch app/liveview_components/__init__.py

Create app/liveview_components/hello.py:

# app/liveview_components/hello.py
from liveview import liveview_handler, send
from django.template.loader import render_to_string

@liveview_handler("say_hello")
def say_hello(consumer, content):
    """Handle 'say_hello' function from client"""
    name = content.get("form", {}).get("name", "World")

    html = render_to_string("hello_message.html", {
        "message": f"Hello, {name}!"
    })

    send(consumer, {
        "target": "#greeting",
        "html": html
    })

Create the template app/templates/hello_message.html:

<h1>{{ message }}</h1>

Step 6: Create the page view and URLs

Create app/views.py:

# app/views.py
from django.shortcuts import render

def home(request):
    return render(request, 'hello_page.html')

Create app/urls.py:

# app/urls.py
from django.urls import path
from . import views

urlpatterns = [
    path('', views.home, name='home'),
]

Update myproject/urls.py:

# myproject/urls.py
from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('', include('app.urls')),
]

Create the page template app/templates/hello_page.html:

<!-- app/templates/hello_page.html -->
{% extends "base.html" %}

{% block content %}
<form>
    <input type="text" name="name" placeholder="Enter your name">
    <button
        data-liveview-function="say_hello"
        data-action="click->page#run">
        Say Hello
    </button>

    <div id="greeting">
        <h1>Hello, World!</h1>
    </div>
</form>
{% endblock %}

Step 7: Run migrations and start server

# Run migrations
python manage.py migrate

# Collect static files (for liveview.min.js)
python manage.py collectstatic --noinput

# Run Django with Daphne (ASGI server)
python manage.py runserver

If you chose Redis: Make sure Redis is running before starting the server.

Visit http://127.0.0.1:8000/ and click the button. You should see real-time updates without page reload! 🎉

Congratulations! You have created your first real-time SPA using Django LiveView.

Complete Example Code

You can find the complete working code from this tutorial at GitHub. Clone it and run with Docker:

git clone git@github.com:Django-LiveView/quick-start.git
cd quick-start
docker compose up

Then visit http://localhost:8000/

Live Demos

Want to see Django LiveView in action? Check out these demos:

  • Alert System: Real-time alert system with WebSocket communication, form validation, and broadcast notifications (source code)

  • Snake Game: The classic game of Snake built entirely with Django LiveView, showcasing real-time keyboard events and dynamic updates