수정 내용
https://devspoon.tistory.com/278
daphne 적용 시 settings의 INSTALLED_APPS 상위에 위치해야 한다.
INSTALLED_APPS = [
'daphne', # 다프네가 제일 앞으로 와야한다. 서순 신경 쓸 것.
'channels',
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sessions",
"django.contrib.messages",
"django.contrib.staticfiles",
]
https://stackoverflow.com/questions/77928535/django-can-login-but-cant-logout-405-method-not-allowed
logout 시, csrf 토큰을 이용한 post 요청만 받기 때문에 form과 버튼이 결합된 형식으로 변경해주어야 한다.
chatPage.html을 수정해주었다.
서비스를 위한 채널의 계층을 다음과 같이 명시해준다. 데이터 공유를 위한 계층이라고 하는데, 보안 취약 문제로 인해 배포시에는 Redis를 이용하는 걸 권장한다.
config/settings.py
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels.layers.InMemoryChannelLayer"
}
}
LOGIN_REDIRECT_URL = "chat-page"
LOGOUT_REDIRECT_URL = "login-user"
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {
"hosts": [("127.0.0.1", 6379)],
},
},
}
redis 이용 시 channels_redis 패키지를 설치해야 한다.
config/asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from ws_chat import routing
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")
application = ProtocolTypeRouter({
"http": get_asgi_application(),
"websocket" : AuthMiddlewareStack(
URLRouter(
routing.websocket_urlpatterns
)
)
})
# ASGI_APPLICATION = 'config.asgi.application'
asgi에 websocket 프로토콜을 추가해주었다. AuthMiddlewareStack는 보안 및 인스턴스 인증, URLRouter는 ws에 대한 라우팅을 담당한다는데... 추가적으로 더 찾아봐야 할 것 같다.
ASGI_APPLICATION 이것도 무슨 역할을 하는지 모르겠다.
채팅 기능을 담당하는 클래스를 만들어주었다. AsyncConsumer와 AsyncWebsocketConsumer을 혼동해서 뭐가 문제인지 찾느라 혼났다...
ws_chat/consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
self.roomGroupName = "group_chat_gfg"
await self.channel_layer.group_add(
self.roomGroupName,
self.channel_name
)
await self.accept()
async def disconnect(self, close_code):
await self.channel.name.group_discard(
self.roomGroupName,
self.channel_name
)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json["message"]
username = text_data_json["username"]
await self.channel_layer.group_send(
self.roomGroupName,
{
"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}))
다음과 같은 기능을 한다고 한다...
connection의 open이랑 created라는 상태가 나오던데 django docs를 찾아봐야 할 듯...
ws_chat/routing.py
from django.urls import path, include
from ws_chat.consumers import ChatConsumer
websocket_urlpatterns = [
path("" , ChatConsumer.as_asgi()) ,
]
채팅 기능을 연결해줄 스크립트이다.
as_asgi()를 통해 비동기 통신이 구현되는 것 같다.