Alright, first question here!
I’m writing a chat application and what i need is for new messages to be displayed immediately, not just after a reload. I don’t know the best way to go about this; maybe reload just the chat-message-container again? Or display new messages as their own chatMessage elements? In either case I wouldn’t know how to do it.
I commented in the JS where I think the required logic needs to be. Any help is much appreciated!!
The HTML and JS:
{% extends "main.html" %} {% block content %}
<main class="messagePage my-xl">
<div class="content-box">
<div class="chat-header">
<a class="backButton" href="{% url 'inbox' %}"><i class="fa-solid fa-arrow-left"></i></a>
<h1 class="username-top">{{ other_user.username }}</h1>
</div>
<div class="chat-message-container">
{% for chat_message in chat_messages %}
<div
class="chatMessage{% if chat_message.sender == profile %} chatMessage--right{% else %} chatMessage--left{% endif %}"
id="chat-messages">
<small>{{ chat_message.content|safe }}</small>
</div>
{% endfor %}
</div>
<div class="chat-bottom-section">
<form method="post" action="" class="chat-form">
{% csrf_token %}
<div class="chat-input">
<input
type="text"
name="content"
class="flex-1 mr-3"
placeholder="Your message..."
id="chat-message-input"
/>
<button id="chat-message-submit">
<span class="icon-btn material-symbols-outlined">send</span>
</button>
</div>
</form>
</div>
</div>
</main>
{% endblock %}
{%block script%}
{{ room.id|json_script:"json-room-id" }}
{{profile.id|json_script:"json-sender-id" }}
{{other_user.id|json_script:"json-receiver-id" }}
<script>
const roomId = JSON.parse(
document.getElementById("json-room-id").textContent
);
const senderId = JSON.parse(
document.getElementById("json-sender-id").textContent
);
const receiverId = JSON.parse(
document.getElementById("json-receiver-id").textContent
);
const chatSocket = new WebSocket(
"ws://" + window.location.host + "/ws/" + roomId + "/"
);
chatSocket.onopen = function (e) {
console.log("yas bitch");
};
chatSocket.onclose = function (e) {
console.log("onclose");
};
chatSocket.onerror = function (e) {
console.error("WebSocket error:", e);
};
chatSocket.onmessage = function (e) {
try {
const data = JSON.parse(e.data);
/*logic to append new messages/reload the css element*/
scrollToBottom();
} catch (error) {
console.error("Error parsing WebSocket data:", error);
}
};
document.querySelector("#chat-message-input").focus();
document.querySelector("#chat-message-input").onkeyup = function (e) {
if (e.keyCode === 13) {
e.preventDefault();
document.querySelector("#chat-message-submit").click();
}
};
document.querySelector("#chat-message-submit").onclick = function (e) {
e.preventDefault();
const messageInputDom = document.querySelector("#chat-message-input");
const message_content = messageInputDom.value;
console.log({
message_content: message_content,
senderId: senderId,
receiverId: receiverId,
roomId: roomId,
});
chatSocket.send(
JSON.stringify({
message_content: message_content,
senderId: senderId,
receiverId: receiverId,
roomId: roomId,
})
);
messageInputDom.value = "";
return false;
};
function scrollToBottom() {
let objDiv = document.getElementById("chat-messages");
objDiv.scrollTop = objDiv.scrollHeight;
}
scrollToBottom();
</script>
{%endblock%}
The view:
@login_required(login_url="login")
def private_chat_view(request, pk):
profile = request.user.profile
room = Room.objects.get(id=pk)
other_user_profile = room.get_partner(profile)
chat_messages = room.messages.all().reverse()
for chat_message in chat_messages:
chat_message.content = insert_line_breaks(chat_message.content)
return render(request, 'chats/room.html', {
'chat_messages': chat_messages,
'room': room,
'profile': profile,
'other_user': other_user_profile
})
I tried both approaches I previously mentioned, in both cases nothing happened.
2
Answers
The fix was using jquery:
You should use django-socketio package to real-time chatting.
pip install django-socketio
socket.connect()
runserver_socektio host:port
Then you can subscribe channiel in client, and send/receive messages.
(socket.send, socket.broadcast ...)
Socket programming is not difficult, but you should learn step by step and you can solve the issue. Good luck.