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! 🏺
1. Setup app and connect Daphne
- Create a new Django project and app:
pip install django daphne
django-admin startproject core .
python manage.py startapp sim
Note: Make sure to use >=Django 4.2 . Otherwise, you will get errors like TypeError: async_generator object is not iterable
when using async views.
(Thanks to Daniel for pointing this out in the Youtube comments)
- Add 'daphne' to
INSTALLED_APPS
incore/settings.py
as the first app. This allows Daphne to hook into Django'srunserver
command. - Add 'sim' to
INSTALLED_APPS
incore/settings.py
(anywhere in the list).
INSTALLED_APPS = [
'daphne',
# ...,
'sim',
# ...
]
- Add the following line to
core/settings.py
:
ASGI_APPLICATION = "core.asgi.application"
2. Add your views
- Add the following views to
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')
3. Add URLs
- Add a URL pattern for the view by adding a
urls.py
file tosim
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'),
]
- Update the URL configuration in
core/urls.py
:
from django.contrib import admin
from django.urls import include, path
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('sim.urls')),
]
4. Add your templates
- Create a
templates
directory insim
. - Create a
sse.html
file insim/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>
Run the app
- Run the Daphne server:
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.
- Visit
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.
Complete ✅
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.
If you want to build an AI chat app using this technique, check out my guide Stream AI chats to the browser using Django in 5 minutes (OpenAI and Anthropic)💧.
P.S Build your Django frontend even faster?
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.