Как добавить страницу (chat) в django-channels-chat.
127.0.0.1:8000
все работает
HTTP GET /api/v1/user/ 200 [0.01, 127.0.0.1:36773]
HTTP GET /api/v1/message/?target=web 200 [0.08, 127.0.0.1:36773]
127.0.0.1:8000/chat
HTTP GET /chat/api/v1/user/ 200 [0.02, 127.0.0.1:36796]
Not Found: /api/v1/message/
HTTP GET /api/v1/message/?target=web 404 [0.03, 127.0.0.1:36796]
settings.py
ALLOWED_HOSTS = ['*']
LOGIN_REDIRECT_URL = '/chat/'
LOGIN_URL = '/chat/login/'
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated'
],
'DEFAULT_PAGINATION_CLASS':
'rest_framework.pagination.LimitOffsetPagination',
'PAGE_SIZE': 100
}
MESSAGES_TO_LOAD = 15
CHANNEL_LAYERS = {
"default": {
"BACKEND": "asgiref.inmemory.ChannelLayer",
"ROUTING": "core.routing.channel_routing",
},
}
ASGI_APPLICATION = 'chat.routing.application'
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
"hosts": [('redis', 6379)],
},
},
}
URLS.py
path('chat/', include('core.urls'))
core.urls.py
from django.urls import path, include
from django.contrib.auth import views as auth_views
from django.views.generic import TemplateView
from django.contrib.auth.decorators import login_required
from rest_framework.routers import DefaultRouter
from core.api import MessageModelViewSet, UserModelViewSet
router = DefaultRouter()
router.register(r'message', MessageModelViewSet, basename='message-api')
router.register(r'user', UserModelViewSet, basename='user-api')
urlpatterns = [
path('api/v1/', include(router.urls)),
path(
'',
login_required(TemplateView.as_view(template_name='core/chat.html')),
name='home',
),
path('login/', auth_views.LoginView.as_view(), name='login'),
path(
'logout/',
auth_views.LogoutView.as_view(template_name='registration/logout.html', next_page=None),
name='logout',
)
]
routing.py
from django.urls import path
from core import consumers
websocket_urlpatterns = [
path('/ws/chat/', consumers.ChatConsumer)
]
consumers.py
import json
from channels.generic.websocket import AsyncWebsocketConsumer
class ChatConsumer(AsyncWebsocketConsumer):
async def connect(self):
user_id = self.scope["session"]["_auth_user_id"]
self.group_name = "{}".format(user_id)
# Join room group
await self.channel_layer.group_add(self.group_name, self.channel_name)
await self.accept()
async def disconnect(self, close_code):
# Leave room group
await self.channel_layer.group_discard(self.group_name, self.channel_name)
# Receive message from WebSocket
async def receive(self, text_data=None, bytes_data=None):
text_data_json = json.loads(text_data)
message = text_data_json["message"]
# Send message to room group
await self.channel_layer.group_send(
self.group_name, {"type": "recieve_group_message", "message": message}
)
async def recieve_group_message(self, event):
message = event["message"]
# Send message to WebSocket
await self.send(text_data=json.dumps({"message": message}))
let currentRecipient = '';
let chatInput = $('#chat-input');
let chatButton = $('#btn-send');
let userList = $('#user-list');
let messageList = $('#messages');
function updateUserList() {
$.getJSON('api/v1/user/', function (data) {
userList.children('.user').remove();
for (let i = 0; i < data.length; i++) {
const userItem = `<a class="list-group-item user">${data[i]['username']}</a>`;
$(userItem).appendTo('#user-list');
}
$('.user').click(function () {
userList.children('.active').removeClass('active');
let selected = event.target;
$(selected).addClass('active');
setCurrentRecipient(selected.text);
});
});
}
function drawMessage(message) {
let position = 'left';
const date = new Date(message.timestamp);
if (message.user === currentUser) position = 'right';
const messageItem = `
<li class="message ${position}">
<div class="avatar">${message.user}</div>
<div class="text_wrapper">
<div class="text">${message.body}<br>
<span class="small">${date}</span>
</div>
</div>
</li>`;
$(messageItem).appendTo('#messages');
}
function getConversation(recipient) {
$.getJSON(`/api/v1/message/?target=${recipient}`, function (data) {
messageList.children('.message').remove();
for (let i = data['results'].length - 1; i >= 0; i--) {
drawMessage(data['results'][i]);
}
messageList.animate({scrollTop: messageList.prop('scrollHeight')});
});
}
function getMessageById(message) {
id = JSON.parse(message).message
$.getJSON(`/api/v1/message/${id}/`, function (data) {
if (data.user === currentRecipient ||
(data.recipient === currentRecipient && data.user == currentUser)) {
drawMessage(data);
}
messageList.animate({scrollTop: messageList.prop('scrollHeight')});
});
}
function sendMessage(recipient, body) {
$.post('/api/v1/message/', {
recipient: recipient,
body: body
}).fail(function () {
alert('Error! Check console!');
});
}
function setCurrentRecipient(username) {
currentRecipient = username;
getConversation(currentRecipient);
enableInput();
}
function enableInput() {
chatInput.prop('disabled', false);
chatButton.prop('disabled', false);
chatInput.focus();
}
function disableInput() {
chatInput.prop('disabled', true);
chatButton.prop('disabled', true);
}
$(document).ready(function () {
updateUserList();
disableInput();
// let socket = new WebSocket(`ws://127.0.0.1:8000/?session_key=${sessionKey}`);
var socket = new WebSocket(
'ws://' + redis + '/ws/chat/' + 'ws?session_key=${sessionKey}')
chatInput.keypress(function (e) {
if (e.keyCode == 13)
chatButton.click();
});
chatButton.click(function () {
if (chatInput.val().length > 0) {
sendMessage(currentRecipient, chatInput.val());
chatInput.val('');
}
});
socket.onmessage = function (e) {
getMessageById(e.data);
};
});