Как добавлять комнаты django channels?
Как на django channels создавать другие каналы, чтобы на их основе сделать личные сообщения пользователей? Я сделал все по гайду, но там только один канал, где может писать любой пользователь.
Полагаю, нужно менять consumer.
def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = 'chat_%s' % self.room_name
async_to_sync(self.channel_layer.group_add)(
self.room_group_name,
self.channel_name
)
self.accept()
Ответы (1 шт):
Автор решения: RoIVIan
→ Ссылка
Вы можете воспользоваться примером, на который ссылается документация Channels - https://github.com/andrewgodwin/channels-examples/tree/master/multichat
У каждого пользователя есть список доступных ему комнат. Нужно доработать модельки и метод get_room_or_error чтобы сообщения получали только те кто должен.
class ChatConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
self.rooms = set()
if self.scope["user"].is_anonymous:
await self.close()
else:
await self.accept()
room_list = await get_room_list(self.scope["user"])
for room in room_list:
await self.channel_layer.group_add(
room.group_name,
self.channel_name,
)
self.rooms.add(room.id)
async def receive_json(self, content):
command = content.get("command", None)
try:
if command == "join":
await self.join_room(content["room"])
...
except ClientError as e:
await self.send_json({"error": e.code})
async def join_room(self, room_id):
room = await get_room_or_error(self.scope["user"], room_id)
if settings.NOTIFY_USERS_ON_ENTER_OR_LEAVE_ROOMS:
await self.channel_layer.group_send(
room.group_name,
{
"type": "chat.join",
"room_id": room_id,
"username": self.scope["user"].username,
}
)
if room_id not in self.rooms:
self.rooms.add(room_id)
await self.channel_layer.group_add(
room.group_name,
self.channel_name,
)
await self.send_json({
"join": str(room.id),
"title": room.title,
})
async def chat_join(self, event):
await self.send_json(
{
"msg_type": settings.MSG_TYPE_ENTER,
"room": event["room_id"],
"username": event["username"],
},
)
Моделька выглядит следующим образом:
class Room(models.Model):
title = models.CharField(max_length=255)
staff_only = models.BooleanField(default=False)
def __str__(self):
return self.title
@property
def group_name(self):
return "room-%s" % self.id
Проверки на доступность комнаты для пользователя
@database_sync_to_async
def get_room_list(user):
if not user.is_authenticated:
raise ClientError("USER_HAS_TO_LOGIN")
# для примера отфильтруем комнаты по staff_only
room = Room.objects.filter(staff_only=user.is_staff)
return room
@database_sync_to_async
def get_room_or_error(user, room_id):
if not user.is_authenticated:
raise ClientError("USER_HAS_TO_LOGIN")
try:
room = Room.objects.get(pk=room_id)
except Room.DoesNotExist:
raise ClientError("ROOM_INVALID")
if room.staff_only and not user.is_staff:
raise ClientError("ROOM_ACCESS_DENIED")
return room