19.6. Django Channels
Websockets in 100 seconds https://www.youtube.com/watch?v=1BfCnjr_Vjg
Django Channels is a project that takes Django and extends its abilities beyond HTTP - to handle WebSockets, chat protocols, IoT protocols, and more. It's built on a Python specification called ASGI.
19.6.1. Install
Run command in system terminal:
$ python -m pip install 'channels[daphne]'
19.6.2. Settings
Append to myproject/settings.py
:
INSTALLED_APPS += ['daphne', 'chat']
ASGI_APPLICATION = 'myproject.asgi.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels.layers.InMemoryChannelLayer',
}
}
Note
During development you can use InMemoryChannelLayer
config.
For production use RedisChannelLayer
(see below).
19.6.3. Template
File chat/templates/chat/index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Chat</title>
</head>
<body>
<h1>Chat</h1>
<form id="form">
<input type="text" id="message" name="message" placeholder="Type your message here">
<button type="submit">Send</button>
</form>
<div id="messages">
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
const ws = new WebSocket('ws://{{ request.get_host }}/ws/chat/');
ws.onmessage = (response) => {
data = JSON.parse(response.data);
switch (data.type) {
case 'system': console.log(data.value); break;
case 'message': onMessage(data.value); break;
}
};
onMessage = (msg) => {
let history = document.getElementById('history');
let message = document.createElement('p');
message.textContent = msg;
history.appendChild(message);
};
const form = document.querySelector('form');
form.addEventListener('submit', (event) => {
event.preventDefault();
ws.send(JSON.stringify({
type: 'message',
value: form.message.value
}));
form.reset();
});
});
</script>
</body>
</html>
19.6.4. View
Append to file myproject/shop/views.py
:
from django.shortcuts import render
def chat(request):
return render(request, 'chat/index.html')
19.6.5. URLs
Append to file myproject/urls.py
:
from chat.views import chat
urlpatterns += [path('chat/', chat, name='chat')]
19.6.6. Consumers
File chat/consumers.py
:
from channels.generic.websocket import JsonWebsocketConsumer
from asgiref.sync import async_to_sync
class ChatConsumer(JsonWebsocketConsumer):
def connect(self):
self.room_group_name = 'chat'
func = async_to_sync(self.channel_layer.group_add)
func(self.room_group_name, self.channel_name)
self.accept()
self.send_json({
'type': 'system',
'value': 'connected',
})
def receive_json(self, content):
func = async_to_sync(self.channel_layer.group_send)
func(self.room_group_name, {
'type': 'handle',
'value': content['value'],
})
def handle(self, event):
self.send_json({
'type': 'message',
'value': event['value'],
})
def disconnect(self, close_code):
self.send_json({
'type': 'system',
'value': 'disconnected',
})
19.6.7. Routing
File chat/routing.py
:
from django.urls import re_path
from .consumers import ChatConsumer
websocket_urlpatterns = [
re_path(r'ws/chat/', ChatConsumer.as_asgi())
]
19.6.8. ASGI
channels.auth.AuthMiddlewareStack
- Uses Django session authenticationIt is not needed for public channels
Modify myproject/asgi.py
:
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
import chat.routing
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myproject.settings')
application = ProtocolTypeRouter({
'http': get_asgi_application(),
'websocket': AuthMiddlewareStack(
URLRouter(chat.routing.websocket_urlpatterns),
),
})
19.6.9. Redis
For production environment
Run command in system terminal:
$ python -m pip install channels_redis
Append to myproject/settings.py
:
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [
('localhost', 6379),
],
},
},
}
19.6.10. Further Reading
Creating a New Conversation https://justdjango.com/blog/chat-app-django-channels#creating-a-new-conversation
Storing Chat History https://justdjango.com/blog/chat-app-django-channels#storing-chat-history
Displaying Active Conversations https://justdjango.com/blog/chat-app-django-channels#displaying-active-conversations
Show a User's Online Status https://justdjango.com/blog/chat-app-django-channels#how-to-show-a-users-online-status
Show When a User is Typing https://justdjango.com/blog/chat-app-django-channels#how-to-show-when-a-user-is-typing
Show New Message Notifications https://justdjango.com/blog/chat-app-django-channels#how-to-show-new-message-notifications