이번에는 gpt의 도움을 몇번 받았다.
channels의 공식 문서를 참고하였는데 아직도 잘 모르겠다...
생각할 수 있는 시나리오가 많아서 고민했었는데, 채팅 시 카카오톡의 오픈 채팅처럼 무작위 채팅에 들어갈 수 있는 형태의 서비스를 생각해보았다.
채팅방의 경우, 생성한 시간순으로 정렬되는 느낌으로...
config/settings.py
LOGIN_REDIRECT_URL = "chat-lobby"
로그인 시 redirect 위치를 로비로 수정해주었다.
templates/ws_chat/chatLobby.html
{% for room in rooms %}
<a href="{% url 'chat_room' room.id %}">{{ room.title }}</a><br>
{% endfor %}
채팅 로비의 경우, 임시로 채팅방 이름만 출력하도록 해두었다. 지금보니 url-name이 잘못되어있다...
consumer는 아래와 같이 수정해줬다.
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.room_name = self.scope['url_route']['kwargs']['room_name']
self.room_group_name = f'chat_{self.room_name}'
await self.channel_layer.group_add(
self.room_group_name,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
await self.channel.name.group_discard(
self.room_group_name,
self.channel_name
)
async def receive(self, text_data):
data = json.loads(text_data)
message = data["message"]
username = data["username"]
await self.channel_layer.group_send(
self.room_group_name,
{
"type" : "sendMessage",
"message" : message,
"username" : username,
} )
async def sendMessage(self, event):
message = event["message"]
username = event["username"]
await self.send(text_data = json.dumps(
{"message" : message, "username" : username}))
형태는 크게 바뀌지 않았다. 채팅방 이름을 채널 레이어에 저장할 수 있게 만들었다!
models.py
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class ChatRoom(models.Model):
title = models.CharField(max_length = 255)
description = models.TextField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self) -> str:
return self.title
class Message(models.Model):
chatroom = models.ForeignKey(ChatRoom, on_delete=models.CASCADE, related_name="messages")
user = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.user.username}: {self.content[:20]}"
DB에 저장해야 하기 때문에 모델을 추가해주었다. 채팅방과 메시지를 기록해준다.
채팅 로비또한 수정했기 때문에 url도 수정해야 한다.
먼저 routing.py의 path를 수정해주었다.
websocket_urlpatterns = [
path("chat/<str:room_name>/" , ChatConsumer.as_asgi()) ,
]
다음으로 urls.py이다. 여기도 비슷하게 추가 및 수정해주었다.
path("", chat_views.chatLobby, name='chat-lobby'),
path("chat/<str:room_name>/", chat_views.chatPage, name="chat-page"),
채팅방을 보여줄 채팅 로비 또한 만들어주어야 한다. views.py를 통해 만들어 주었다.
def chatLobby(request, *args, **kwargs):
if not request.user.is_authenticated:
return redirect("login-user")
# order by recently
rooms = ChatRoom.objects.order_by("-created_at")
return render(request, "ws_chat/chatLobby.html", {"rooms": rooms})
채팅 로비의 경우 아직 보여주는 것만 존재하고 생성이 안되기 때문에 현재 서버를 키게 되면 아무것도 없는 빈 화면이 출력된다.
다음에는 채팅방의 CRUD 기능을 추가해야 할 것 같다.