0
I’m working on a Django project using Django Channels with Redis as the channel layer. My setup allows WebSocket connections, and I am able to send and receive data from Redis without issues. However, when I try to send data to specific WebSocket channels using self.channel_layer.send, the send_online_users method in my AsyncWebsocketConsumer is not triggered.
I’ve verified that my Redis server is working and communicating with the Django server. The channels and users are being stored correctly in Redis. The self.channel_layer.send() function runs without throwing errors, but the send_online_users method is never triggered (the print statements inside send_online_users do not show in the logs).
Here is my Consumers.py code:
from channels.generic.websocket import AsyncWebsocketConsumer
import redis
from django.conf import settings
import redis.client
from asgiref.sync import sync_to_async
import json
from channels.layers import get_channel_layer
redis_client = redis.StrictRedis(host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=0)
class UserActivityConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.user = self.scope['user']
if self.user.is_anonymous or not self.user.is_authenticated:
await self.close()
else:
self.channel_name = f'user_activity_{self.user.username}'
await sync_to_async(redis_client.sadd)('online_users', self.user.id)
await sync_to_async(redis_client.sadd)("online_channels",self.channel_name)
await self.accept()
await self.send_to_all()
async def disconnect(self,close_code):
user_id = self.scope['user'].id
await sync_to_async(redis_client.srem)("online_users", user_id)
await sync_to_async(redis_client.srem)("online_channels", self.channel_name)
await self.send_to_all()
async def send_to_all(self):
try:
online_users = await sync_to_async(redis_client.smembers)("online_users")
online_users = [int(user_id) for user_id in online_users]
online_channels = await sync_to_async(redis_client.smembers)("online_channels")
channel_layer = get_channel_layer()
for channel_name in online_channels:
channel_name = channel_name.decode()
await self.channel_layer.send(str(channel_name), {
"type": "send_online_users",
"online_users": online_users
})
except Exception as e:
print(e)
async def send_online_users(self, event):
try:
print('TRIGGERED - send_message')
online_users = event.get('online_users', [])
print(f"Online users: {online_users}")
await self.send(text_data=json.dumps({
"type": "online_users",
"online_users": online_users
}))
print('Message sent to WebSocket client')
except Exception as e:
print(f"Error in send_message: {e}")
additionally the frontend code:
useEffect(() => {
getOnlineUsers();
return () => {
if (socket) {
socketRef.current.close();
}
};
}, []);
const getOnlineUsers = async () => {
if (!socketRef.current || socketRef.current.readyState === WebSocket.CLOSED) {
try {
const token = localStorage.getItem('auth_token');
socketRef.current = new WebSocket(`ws://192.168.1.101:8000/ws/activity/?token=${token}`);
setSocket(socketRef.current);
socketRef.current.onopen = () => {
console.log('WebSocket connection established DM');
};
socketRef.current.onclose = () => {
console.log('WebSocket connection closed DM');
};
socketRef.current.onmessage = (event) => {
const data = JSON.parse(event.data);
if (data.type === "online_users") {
console.log('received');
setOnlineUsers(data.online_users);
}
};
} catch (error) {
console.log(error);
}
}
};
Additional Context: I have a real time chat system and it works perfectly well and in the chat consumer im assigning 2 users to a specific group and i’m using self.channel_layer.group_send(GROUP_NAME,{…}) method and it runs perfectly fine, the messages are being sent with no issues but when i try to send data with “CHANNEL_NAME” it does not work. All servers (frontend vite + Django + Redis server) run in a linux virtual machine with VM Box and bridge adaptor network settings
Django Channels Configuration:
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('192.168.1.101', 6379)],
},
},
}
What I’m expecting:
When I call self.channel_layer.send(channel_name, {…}), it should trigger the send_online_users method, which sends the list of online users to the WebSocket client.
What happens:
The send_online_users method is never triggered. Even the print statements doesn’t run and no data is sent to the client.