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

[WebSocket/Django] Chatting : DB 저장하기

alsruds 2023. 3. 23. 03:46

20230307

 

[ WebSocket Chatting 기본 설정 ]

》 Tutorial Part 1/2/3

https://channels.readthedocs.io/en/stable/

 

Django Channels — Channels 4.0.0 documentation

Channels is a project that takes Django and extends its abilities beyond HTTP - to handle WebSockets, chat protocols, IoT protocols, and more. It’s built on a Python specification called ASGI. Channels builds upon the native ASGI support in Django. Whils

channels.readthedocs.io

 

● 템플릿에 적용

》 채팅 목록방

          > 로그인 기능 구현

          > 팔로워 기능 구현

          > 팔로우하고 있는 사람 목록 출력

 

》 채팅방

 

[ 채팅내역 DB 저장하기 ]

참고 : https://a-littlecoding.tistory.com/27

 

Django channels 실시간 채팅 기능 (websocket)

공식문서 + 구글링 + 유튜브를 통해 실시간 채팅 기능 구현(서버 api 동기식) 스파르타 내배캠 4번째 팀 프로젝트 실시간 채팅 기능 담당. 간단하게 프로젝트 소개를 하고 Django channels를 이용한 실

a-littlecoding.tistory.com

 

DB 생성

from django.db import models

# 같은 채팅방 입장
class Room(models.Model):
    room_number = models.IntegerField()
    from_user = models.CharField(max_length=30)
    to_user = models.CharField(max_length=30)

# 채팅 내역 저장
class Chatting(models.Model):
    room_id = models.IntegerField()
    message = models.TextField()
    to = models.IntegerField()
    from_user = models.IntegerField()

 

채팅방에 입장할 때 실행되는 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}/`
    );

    # 채팅 입력 시 화면에 출력
    chatSocket.onmessage = (e) => {
        let data = JSON.parse(e.data);
        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):
    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에서 chatSocket.send() 시 연결되는 함수
    async def receive(self, text_data):
        data = json.loads(text_data)
        await self.commands[data['command']](self, data)

    # Receive message from WebSocket (채팅 입력)
    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}
        )

    # 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()

    commands = {
        'new_messages': new_messages
    }

 

 

☞ 채팅 영상 ☜