1. Channels Setup
pip install channels channels-redis
# settings.py
INSTALLED_APPS = [..., 'channels']
ASGI_APPLICATION = 'config.asgi.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {'hosts': [('127.0.0.1', 6379)]},
},
}
# asgi.py
import os
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
application = ProtocolTypeRouter({
'http': get_asgi_application(),
'websocket': AuthMiddlewareStack(
URLRouter([
path('ws/chat/<str:room_name>/', ChatConsumer.as_asgi()),
path('ws/notifications/', NotificationConsumer.as_asgi()),
])
),
})
2. WebSocket Consumer
import json
from channels.generic.websocket import AsyncJsonWebsocketConsumer
class ChatConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group = f'chat_{self.room_name}'
await self.channel_layer.group_add(self.room_group, self.channel_name)
await self.accept()
async def disconnect(self, close_code):
await self.channel_layer.group_discard(self.room_group, self.channel_name)
async def receive_json(self, content):
message = content['message']
user = self.scope['user']
await self.channel_layer.group_send(
self.room_group,
{
'type': 'chat_message',
'message': message,
'username': user.username,
},
)
async def chat_message(self, event):
await self.send_json({
'message': event['message'],
'username': event['username'],
})
3. Real-time Notifications
class NotificationConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
user = self.scope['user']
if user.is_anonymous:
await self.close()
return
self.group_name = f'notifications_{user.id}'
await self.channel_layer.group_add(self.group_name, self.channel_name)
await self.accept()
async def send_notification(self, event):
await self.send_json(event['data'])
# Gửi notification từ anywhere
from channels.layers import get_channel_layer
from asgiref.sync import async_to_sync
def notify_user(user_id, message):
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
f'notifications_{user_id}',
{'type': 'send_notification', 'data': {'message': message}},
)
4. Frontend WebSocket
const ws = new WebSocket(`wss://${location.host}/ws/chat/${roomName}/`);
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
appendMessage(data.username, data.message);
};
ws.onclose = () => {
setTimeout(() => connectWebSocket(), 3000); // Reconnect
};
function sendMessage(message) {
ws.send(JSON.stringify({ message }));
}
Bài tiếp theo: Celery, Signals & Caching.