websocket → 비동기
wsgi와 asgi
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "gaggamagga.settings")
django_asgi_app = get_asgi_application()
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from notification import routing
application = ProtocolTypeRouter(
{
"http": django_asgi_app,
"websocket" : AuthMiddlewareStack(
URLRouter(
routing.websocket_urlpatterns
)
)
}
)
from django.urls import re_path
from . import consumers
websocket_urlpatterns = [
re_path(r"ws/notification/(?P<room_name>\\w+)/$",consumers.NotificationConsumer.as_asgi()),
]
from channels.generic.websocket import AsyncWebsocketConsumer
from channels.db import database_sync_to_async
import json
from .models import Notification
class NotificationConsumer(AsyncWebsocketConsumer):
@database_sync_to_async
def create_notification(self, message, author):
return Notification.objects.create(content=message, user_id=author)
async def connect(self) :
self.room_name = self.scope["url_route"]["kwargs"]["room_name"]
await self.channel_layer.group_add(self.room_name, self.channel_name)
await self.accept()
async def disconnect(self, code):
# 그룹 떠남
await self.channel_layer.group_discard(self.room_name, self.channel_name)
async def receive(self, text_data):
text_data_json = json.loads(text_data)
message = text_data_json["message"]
author = text_data_json["author"]
user_id = text_data_json["user_id"]
event = {
'type': 'send_message',
'message': message,
"author" : author,
"user_id" : user_id
}
# DB 저장
if int(author) != user_id :
save_message = await self.create_notification(message=message, author=author)
# 그룹에 메시지 보내기
await self.channel_layer.group_send(self.room_name, event)
# 그룹에서 메시지 받기
async def send_message(self, event):
message = event["message"]
author = event["author"]
user_id = event["user_id"]
# 웹소켓에 메시지 보내기
await self.send(text_data=json.dumps({'message':message, 'author':author, "user_id":user_id}))
// 알람
const notificationSocket = new WebSocket(
'wss://'
+ "www.back-gaggamagga.tk"
+ '/ws/notification/'
+ author_id
+ '/'
);
notificationSocket.onmessage = async function (e) {
const data = JSON.parse(e.data);
const alarmBox = document.querySelector('.alarm')
if (payload_parse.user_id == author_id) {
const alarmContent = document.createElement('div')
alarmContent.style.display = "flex"
alarmContent.style.height = "10vh"
alarmContent.innerHTML = data.message
alarmBox.appendChild(alarmContent)
const response = await fetch(`${backendBaseUrl}/notification/${payload_parse.user_id}/`, {
headers: {
"authorization": "Bearer " + localStorage.getItem("access")
},
method: 'GET'
})
.then(response => response.json())
const notificationButton = document.createElement('button')
const notificationButtonText = document.createTextNode('확인')
notificationButton.appendChild(notificationButtonText)
notificationButton.onclick = async function () {
await fetch(`${backendBaseUrl}/notification/alarm/${response[0].id}/`, {
headers: {
'content-type': 'application/json',
"authorization": "Bearer " + localStorage.getItem("access")
},
method: 'PUT',
body: ''
})
alarmBox.innerHTML = ""
getNotification()
}
alarmContent.appendChild(notificationButton)
}
};
notificationSocket.onclose = function (e) {
console.error('소켓이 닫혔어요 ㅜㅜ');
};
function alarm() {
if (payload_parse.user_id != author_id) {
const message = `<img src="<https://cdn-icons-png.flaticon.com/512/1827/1827422.png>" class="modal-icon"><a style="cursor:pointer;margin:auto; text-decoration:none;" href="review_detail.html?id=${review_id}&place=${place_id}&author=${author_id}">
<p class="alarm-content">후기에 덧글이 달렸습니다.</p></a>`
notificationSocket.onopen = () => notificationSocket.send(JSON.stringify({
'message': message,
"author": author_id,
"user_id": payload_parse.user_id
}
))
}
}
from django.urls import path
from . import views
urlpatterns = [
# Notification
path('<int:user_id>/', views.NotificationView.as_view(), name='notification'),
path('alarm/<int:notification_id>/', views.NotificationDetailView.as_view(), name="notification_detail"),
]
from django.urls import path
from . import views
urlpatterns = [
# Notification
path('<int:user_id>/', views.NotificationView.as_view(), name='notification'),
path('alarm/<int:notification_id>/', views.NotificationDetailView.as_view(), name="notification_detail"),
]
class NotificationConsumer(AsyncWebsocketConsumer):
@database_sync_to_async
def create_notification(self, message, author):
return Notification.objects.create(content=message, user_id=author)
window.onload = () => {
getNotification() //알람
}
notificationSocket.onmessage = async function (e) {
const data = JSON.parse(e.data);
const alarmBox = document.querySelector('.alarm')
if (payload_parse.user_id == author_id) {
const alarmContent = document.createElement('div')
alarmContent.style.display = "flex"
alarmContent.style.height = "10vh"
alarmContent.innerHTML = data.message
alarmBox.appendChild(alarmContent)
const response = await fetch(`${backendBaseUrl}/notification/${payload_parse.user_id}/`, {
headers: {
"authorization": "Bearer " + localStorage.getItem("access")
},
method: 'GET'
})
.then(response => response.json())
const notificationButton = document.createElement('button')
const notificationButtonText = document.createTextNode('확인')
notificationButton.appendChild(notificationButtonText)
notificationButton.onclick = async function () {
await fetch(`${backendBaseUrl}/notification/alarm/${response[0].id}/`, {
headers: {
'content-type': 'application/json',
"authorization": "Bearer " + localStorage.getItem("access")
},
method: 'PUT',
body: ''
})
alarmBox.innerHTML = ""
getNotification()
}
alarmContent.appendChild(notificationButton)
}
};
async function getNotification() {
const response = await fetch(`${backendBaseUrl}/notification/${payload_parse.user_id}/`, {
headers: {
"authorization": "Bearer " + localStorage.getItem("access")
},
method: 'GET'
})
.then(response => response.json())
response.forEach(notification => {
const alarmBox = document.querySelector('.alarm')
let alarmContent = document.createElement('div')
alarmContent.setAttribute("id", `alarm${notification.id}`)
alarmContent.innerHTML = notification.content
alarmContent.style.display = "flex"
alarmContent.style.height = "10vh"
alarmBox.appendChild(alarmContent)
const notificationButton = document.createElement('button')
const notificationButtonText = document.createTextNode('확인')
notificationButton.appendChild(notificationButtonText)
notificationButton.onclick = async function () {
await fetch(`${backendBaseUrl}/notification/alarm/${notification.id}/`, {
headers: {
'content-type': 'application/json',
"authorization": "Bearer " + localStorage.getItem("access")
},
method: 'PUT',
body: ''
})
alarmBox.innerHTML = ""
getNotification()
}
alarmContent.appendChild(notificationButton)
})
}