Adding server sent events to your Django app is simple and powerful. It allows you to push updates to your frontend without the frontend needing to send requests, such as polling.
I'll show you the simplest way (with the least code) to add server sent events to your Django app.
We'll use Daphne. This is a production ASGI server that hooks into Django (relevant Django docs here) and its existing runserver
command.
The final product will look like the below. All data is being sent from the server to the frontend in real-time, without the frontend needing to send requests.
Optional video tutorial (featuring me) below 📽️:
Let's start! 🏺
pip install django daphne
django-admin startproject core .
python manage.py startapp sim
INSTALLED_APPS
in core/settings.py
as the first app. This allows Daphne to hook into Django's runserver
command.INSTALLED_APPS
in core/settings.py
(anywhere in the list).INSTALLED_APPS = [
'daphne',
# ...,
'sim',
# ...
]
core/settings.py
:ASGI_APPLICATION = "core.asgi.application"
sim/views.py
:import asyncio
import random
from django.http import StreamingHttpResponse
from django.shortcuts import render
async def sse_stream(request):
"""
Sends server-sent events to the client.
"""
async def event_stream():
emojis = ["🚀", "🐎", "🌅", "🦾", "🍇"]
i = 0
while True:
yield f'data: {random.choice(emojis)} {i}\n\n'
i += 1
await asyncio.sleep(1)
return StreamingHttpResponse(event_stream(), content_type='text/event-stream')
def index(request):
return render(request, 'sse.html')
urls.py
file to sim
with the following content:from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('stream/', views.sse_stream, name='sse_stream'),
]
core/urls.py
:from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('sim.urls')),
]
templates
directory in sim
.sse.html
file in sim/templates
with the following content:<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>SSE</title>
</head>
<body>
<h1>Server Sent Events</h1>
<div id="sse-data"></div>
<button onclick="startSSE()">Start</button>
<button onclick="stopSSE()" disabled>Stop</button>
<script>
let eventSource;
const sseData = document.getElementById('sse-data');
function startSSE() {
eventSource = new EventSource('/stream/');
eventSource.onmessage = event => sseData.innerHTML += event.data + '<br>';
document.querySelector('button[onclick="startSSE()"]').disabled = true;
document.querySelector('button[onclick="stopSSE()"]').disabled = false;
}
function stopSSE() {
if (eventSource) {
eventSource.close();
}
document.querySelector('button[onclick="startSSE()"]').disabled = false;
document.querySelector('button[onclick="stopSSE()"]').disabled = true;
}
</script>
</body>
</html>
python manage.py runserver
You should see something like the following output (notice the Daphne server is running):
Django version 4.2.7, using settings 'core.settings'
Starting ASGI/Daphne version 4.0.0 development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
http://127.0.0.1:8000/sse/
in your browser. You should see the numbers 0 to 9 appear at one-second intervals. You should be able to start and stop the server sent events by clicking the buttons.That's it - You've added server sent events to your Django app 🎉. This is a minimal example to start using server-sent events with Django and Daphne.
You can now build on this to add real-time updates to your frontend.
Good uses include when your backend receives new data or when a user takes an action.
Probably like you, I want to make my Django product ideas become reality as soon as possible.
That's why I built Photon Designer - a new way of building Django frontend as fast as possible, and entirely visually.
Photon Designer outputs neat, clean Django templates.