CLOUD/[P] 실시간 채팅 프로그램

[WebSocket/Django] Chatting : DB 불러오기

alsruds 2023. 3. 23. 04:17

20230308

 

[ 기존 채팅 내역 불러오기 ]

● HTML 수정 (웹소켓 연결할 때)

<script type="text/javascript">
    let roomName = "{{ room_id | escapejs }}";
    let to = "{{ to | escapejs }}";

    # WebSocket 연결
    let chatSocket = new WebSocket(
        `ws://${window.location.host}/ws/chatroom/${roomName}/`
    );

    # WebSocket 연결되자마자 실행 (DB 불러오기)
    chatSocket.onopen = (e) => {
        chatSocket.send(JSON.stringify({'command' : 'return_messages'}))
    };

    # 채팅방 화면에 출력
    chatSocket.onmessage = (e) => {
        let data = JSON.parse(e.data);

        # 기존 채팅 내역 불러오기
        if (data['command'] == 'return_messages') {
            let messages = data['messages'];

            for (const i in messages) {
                document.querySelector("#chat-log").value += (messages[i]['from_user'] + ' : ' + messages[i]['message'] + '\n');
            }
        } 
        # 새로운 채팅 입력
        else {
            let message = data['message'];
            let from_user = data['from_user'];
            document.querySelector("#chat-log").value += (from_user+' : ' + message + '\n');
        }
    };

    chatSocket.onclose = (e) => {
        console.error('Chat socket closed unexpectedly');
    };

    document.querySelector("#chat-message-input").focus();
    document.querySelector("#chat-message-input").addEventListener("keyup",(e) => {
        if (e.keyCode === 13) {
            document.querySelector("#chat-message-submit").click();
        }
    });

    # consumers.py 에 전달
    document.querySelector("#chat-message-submit").addEventListener("click", (e) => {
        let messageInputDom = document.querySelector("#chat-message-input");
        let message = messageInputDom.value;
        chatSocket.send(JSON.stringify({
            'command': 'new_messages',
            'message' : message,
            'to_user' : to,
            'from_user' : {{ request.session.user_uid }},
            'room_id' : roomName
        }));

        messageInputDom.value = '';
    });

</script>

 

consumers.py 수정

import json

from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncWebsocketConsumer
from chat01.models import Chatting

class ChatConsumer(AsyncWebsocketConsumer):
    # WebSocket 연결될 때
    async def connect(self):
        self.room_name = self.scope["url_route"]["kwargs"]["room_id"]
        self.room_group_name = "chat_%s" % self.room_name

        # Join room group
        await self.channel_layer.group_add(self.room_group_name, self.channel_name)

        await self.accept()

    async def disconnect(self, close_code):
        # Leave room group
        await self.channel_layer.group_discard(self.room_group_name, self.channel_name)

    # js code에서 데이터 넘겨받기
    async def receive(self, text_data):
        data = json.loads(text_data)
        await self.commands[data['command']](self, data)

    # 새 채팅 입력
    async def new_messages(self, text_data):
        text_data_json = text_data

        message = text_data_json["message"]
        from_user = text_data_json["from_user"]
        to_user = text_data_json["to_user"]
        room_id = text_data_json["room_id"]

        await self.save_message(to_user, from_user, message, room_id)

        # Send message to room group
        await self.channel_layer.group_send(
            self.room_group_name, {"type": "chat_message", "from_user": from_user, "message": message}
        )

    # Receive message from room group
    async def chat_message(self, event):
        message = event["message"]
        from_user = event["from_user"]
        # Send message to WebSocket
        await self.send(text_data=json.dumps({"command":"receive_message", "from_user": from_user, "message": message}))

    # DB 저장
    @database_sync_to_async
    def save_message(self, to, from_user, message, room_id):
        chatting = Chatting()
        chatting.to = to
        chatting.from_user = from_user
        chatting.message = message
        chatting.room_id = room_id
        return chatting.save()

    # 저장된 메세지 불러오기
    async def return_message(self, data):
        messages = await self.return_db()
        content = {
            'command': 'return_messages',
            'messages': messages
        }

        await self.send(text_data=json.dumps(content))

    @database_sync_to_async
    def return_db(self):
        result = Chatting.objects.filter(room_id=self.room_name)
        messages = []

        for message in result:
            messages.append({'to_user': message.to, 'from_user': message.from_user, 'message': message.message})
        return messages

    commands = {
        'return_messages': return_message,
        'new_messages': new_messages
    }

 

 

☞ 채팅 영상 ☜