Quick Start
Get your first SSE endpoint up and running in 3 steps — no configuration required.
1. Write a generator view
myapp/views.py
import time
from django_flosse import sse_stream, SSEEvent
from django_flosse.permissions import IsAuthenticated
@sse_stream(permission_classes=[IsAuthenticated])
def progress(request):
for i in range(1, 11):
yield ("progress", {"step": i, "total": 10, "pct": i * 10})
time.sleep(1)
yield SSEEvent(data="All done!", event="complete")
What's happening here?
@sse_streamturns your generator into a fully-featured SSE endpoint.- Each
yieldsends an event to the browser immediately. SSEEventgives you full control over the event name, ID, and retry delay.IsAuthenticatedblocks unauthenticated requests with a403.
2. Wire up the URL
myapp/urls.py
from django.urls import path
from .views import progress
urlpatterns = [
path("sse/progress/", progress),
]
3. Listen in the browser
myapp/templates/progress.html
const source = new EventSource("/sse/progress/");
source.addEventListener("progress", (e) => {
const { step, total, pct } = JSON.parse(e.data);
console.log(`Step ${step}/${total} — ${pct}%`);
});
source.addEventListener("complete", (e) => {
console.log(e.data); // "All done!"
source.close();
});
source.addEventListener("error", () => {
source.close();
});
What you get for free
Every @sse_stream view automatically handles:
| What | How |
|---|---|
| Correct headers | Content-Type: text/event-stream |
| No proxy buffering | X-Accel-Buffering: no |
| No caching | Cache-Control: no-cache, no-transform |
| Permission checks | Returns 403 if any class denies access |
| Error events | Exceptions are streamed as event: error |
| JSON serialisation | Dicts and non-strings are serialised for you |
Next steps
-
Yield Styles
Learn all the ways you can yield events.
-
Permissions
Protect your streams with built-in or custom permission classes.
-
Heartbeats
Keep connections alive when proxies might close idle streams.
-
Deployment
Run in production with Gunicorn, Uvicorn, or Nginx.