21.6. Django Channels — Python
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.
21.6.1. Install
Run command in system terminal:
$ python -m pip install 'channels[daphne]'
21.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).
21.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>
21.6.4. View
Append to file myproject/shop/views.py:
from django.shortcuts import render def chat(request): return render(request, 'chat/index.html')
21.6.5. URLs
Append to file myproject/urls.py:
from chat.views import chat urlpatterns += [path('chat/', chat, name='chat')]
21.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', })
21.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()) ]
21.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), ), })
21.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": [ ('127.0.0.1', 6379), ], }, }, }
21.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