작성
·
43
0
#consumers.py
from asgiref.sync import async_to_sync
from channels.generic.websocket import JsonWebsocketConsumer
from chat.models import Room
# 모든 유저가 고정된 채널 레이어 그룹을 가질것.
class ChatConsumer(JsonWebsocketConsumer):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
SQUARE_GROUP_NAME = "square"
self.group_name = [SQUARE_GROUP_NAME]
self.room = None
def connect(self):
user = self.scope['user']
if not user.is_authenticated:
self.close()
else:
room_name = self.scope['url_route']['kwargs']['room_pk']
try:
self.room = Room.objects.get(pk=room_name)
except Room.DoesNotExist: #지정 룸 pk에 룸 인스턴스가 없을 경우 웹소켓 연결요청 수락.
pass
else:
self.group_name = self.SQUARE_GROUP_NAME
is_new_join = self.room.user_join(self.channel_name, user)
if is_new_join:
async_to_sync(self.channel_layer.group_send)(
self.group_name,
{
"type": "chat.user.join",
"username": user.username,
}
)
async_to_sync(self.channel_layer.group_add)(
self.group_name,
self.channel_name
)
self.accept()
def disconnect(self, code):
if self.group_name:
async_to_sync(self.channel_layer.group_discard)(
self.group_name,
self.channel_name
)
user = self.scope['user']
if self.room is not None:
is_last_leave = self.room.user_leave(self.channel_name, user)
if is_last_leave:
async_to_sync(self.channel_layer.group_send)(
self.group_name,
{
"type": "chat.user.leave",
"username": user.username,
}
)
def chat_user_join(self, message_dict):
self.send_json({
"type": "chat.user.join",
"username": message_dict["username"],
})
def chat_user_leave(self, message_dict):
self.send_json({
"type": "chat.user.leave",
"username": message_dict["username"],
})
def chat_message(self, message_dict):
self.send_json({
"type": "chat.message",
"message": message_dict["message"],
"sender": message_dict["sender"],
})
def receive_json(self, content, **kwargs):
user = self.scope["user"]
_type = content["type"]
if _type == "chat.message":
message = content["message"]
sender = user.username
async_to_sync(self.channel_layer.group_send)(
self.SQUARE_GROUP_NAME,
{
"type": "chat.message",
"message": message,
"sender": sender,
}
)
else:
print(f"Invalid message type : ${_type}")
room_name = self.scope['url_route']['kwargs']['room_pk']
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
KeyError: 'room_pk'
이런 에러가 나서, urls.py, views.py, index.html도 맞춰줘 봤지만, 잘 해결이 되질 않습니다. 어떤식으로 이 에러를 처리해야할까요. 오늘도 좋은 하루 되시길 바랍니다.
감사합니다.
답변 1
1
안녕하세요.
self.scope["url_route"]["kwargs"] 사전은 websocket_urlpatterns 에 명시한 path에 정의한 값들로 구성됩니다. 장고 View 함수에서 인자로 전달받는 값과 같습니다.
그러니 path("ws/chat/<int:room_pk>/", ...) 처럼 room_pk 항목이 있으셔야 합니다.
살펴보시고 댓글 남겨주세요. :-)
Room 은 채팅방 접속 여부를 확인할 목적일 뿐이구요.
단일 채팅방만 운영하실 경우, 그룹명이 정해져있는 것이니까 굳이 따로 광장채팅방 room을 생성하실 필요가 없을 듯 하구요.
Consumer에서 속할 그룹명이 정해져있는 상황이니, 앞선 liveblog 예시처럼 Consumer 클래스의 groups 리스트 속성으로 groups = ["square"] 로 쓰시면, consumer에서 알아서 지정 그룹에 추가하고 제거까지 해줍니다.
지금 채팅방 입장 퇴장 알림 부분을 하고 있었습니다.
이 부분을 하기 위해서 모델과 연동하여 하는데, 제 생각에는 여태까지 채팅 Url을 Room 모델과 관계없이 그냥 열어서 쓰다가 발생한거같습니다. 채팅방 만들기 기능을 안넣고, 그냥 광장채팅방만 만들어서 쓰려고 하거든요. 이런 경우는 room 모델에 그냥 광장채팅방 이름을 만들어서 넣어주면 되는건가요?