I am making a website, this website has a chat app include, the chat app works perfect, but there is a thing I want to do but I dont know how to do it. So I have this chat view chat view, here is were there is the websocket and all that stuff, But in this view this view, is the place were I want the user to see all the chat rooms he is in, on the side of chats like the two example users that are in there. the problem is that I don´t know how to do it. can someone tell me how to do it? with a simple example, like a very simple chat, that the chats of the user appear in the home page?, thanks for the help.
My code: Chat room html or thread:
{% extends "base.html" %}
{% block content %}
<section class="msger" id="prueba">
<header class="msger-header">
<div class="msger-header-title">
<i id="The_other_user"></i>{% if user != object.first %}{{ object.first }}{% else %}{{ object.second }}{% endif %}
</div>
<div class="msger-header-options">
<span><i class="fas fa-comment-alt"></i></span>
</div>
</header>
<main class="msger-chat">
<div class="msg left-msg">
<div
class="msg-img"
style="background-image: url(https://image.flaticon.com/icons/svg/327/327779.svg)"
></div>
<div class="msg-bubble">
<div class="msg-info">
<div class="msg-info-name">BOT</div>
<div class="msg-info-time"></div>
</div>
<div class="msg-text">
Hola, bienvenid@ al Chat! Manda un mensaje para tener cita con la Consultora. Puedes mirar el boton de como pedir consulta😄
</div>
</div>
</div>
{% for chat in object.chatmessage_set.all %}
<div class="msg right-msg" class="msg">
<div class="msg-img" style="background-image: url(https://cdn.xl.thumbs.canstockphoto.com/user-icon-person-profile-sign-vector-avatar-illustration-office-human-web-symbol-business-man-image_csp63452775.jpg)"></div>
<div class="msg-bubble">
<div class="msg-info">
<div class="msg-info-name">{{ chat.user }}</div>
<div class="msg-info-time"></div>
</div>
<div class="msg-text">{{ chat.message }}</div>
</div>
</div>
{% endfor %}
</main>
<form id='form' method='POST' class="msger-inputarea"> {% csrf_token %}
<input type='hidden' id='myUsername' value='{{ user.username }}' />
{{ form }}
<input type="submit" class="msger-send-btn">
</form>
</section>
<!--The Back button and Help-->
<a href="/messages" class="back"><i class="fa fa-arrow-left"></i></a>
<a class="tooltip demo" href="" data-tooltip="Empieza por decir tu nombre completo, despues di la razon de una consulta, di cuantos familiares niños tienes y tambien menciona cuanto tiempo llevas con ese problema. Seras respondid@ en menos de 2 dias">
Como pedir consulta
</a>
{% endblock %}
{% block script %}
<script src='https://cdnjs.cloudflare.com/ajax/libs/reconnecting-websocket/1.0.0/reconnecting-websocket.js'>
</script>
<script>
// websocket scripts
// console.log(window.location)
var loc = window.location
var formData = $("#form")
var msgInput = $("#id_message")
var chatHolder = $("#chat-items")
var me = $("#myUsername").val()
var he = $("#The_other_user")
var user = $(".msg-info-name").text();
const PERSON_IMG = "https://cdn.xl.thumbs.canstockphoto.com/user-icon-person-profile-sign-vector-avatar-illustration-office-human-web-symbol-business-man-image_csp63452775.jpg";
const msgerChat = $(".msger-chat");
const msger = $(".msger");
var wsStart = 'ws://'
if (loc.protocol == 'https:') {
wsStart = 'wss://'
}
var endpoint = wsStart + loc.host + loc.pathname + '/'
var socket = new ReconnectingWebSocket(endpoint)
socket.onmessage = function(e){
console.log("message", e)
var chatDataMsg = JSON.parse(e.data)
// chatHolder.append("<li>" + chatDataMsg.message + " via " + chatDataMsg.username + "</li>")
// Append the message frontend
var side_append = "msg right-msg";
if (chatDataMsg.username != me) {
var side_append = "msg left-msg";
};
msgerChat.append(`
<div class="${side_append}" class="msg">
<div class="msg-img" style="background-image: url(${PERSON_IMG})"></div>
<div class="msg-bubble">
<div class="msg-info">
<div class="msg-info-name">${chatDataMsg.username}</div>
<div class="msg-info-time">${formatDate(new Date())}</div>
</div>
<div class="msg-text">${chatDataMsg.message}</div>
</div>
</div>
`)
// Utils
msgerChat.scrollTop += 500;
function get(selector, root = document) {
return root.querySelector(selector);
}
function formatDate(date) {
const h = "0" + date.getHours();
const m = "0" + date.getMinutes();
return `${h.slice(-2)}:${m.slice(-2)}`;
}
scrollWin()
}
socket.onopen = function(e){
console.log("open", e)
formData.submit(function(event){
event.preventDefault()
var msgText = msgInput.val()
// chatHolder.append("<li>" + msgText + " via " + me + "</li>")
var finalData = {
'message': msgText
}
socket.send(JSON.stringify(finalData))
formData[0].reset()
})
}
socket.onerror = function(e){
console.log("error", e)
}
socket.onclose = function(e){
console.log("close", e)
}
window.onload = function() {
scrollWin()
}
//Scroll auto funct
const chatContainer = document.querySelector(".msger-chat");
function scrollWin() {
chatContainer.scrollTo(0, chatContainer.scrollHeight)
}
$( ".msg" ).each(function() {
var users = $(this).find(".msg-info-name").text();
if (users != me) {
$(this).removeClass("msg right-msg");
$(this).addClass("msg left-msg");
};
});
</script>
{% endblock %}
the messages room, were I want to see all users chat rooms:
{% load static %}
<!DOCTYPE html>
<head>
<title>Consultoria</title>
<script src="https://kit.fontawesome.com/e66aaa0c91.js" crossorigin="anonymous"></script>
<link rel='stylesheet' type='text/css' href="{% static 'css/chats.css' %}">
<link rel='stylesheet' type='text/css' href="{% static 'css/cards.css' %}">
<link rel='stylesheet' type='text/css' href="{% static 'css/buttons.css' %}">
<style>
a{text-decoration:none}
</style>
</head>
<body>
<!--The Message chats-->
<div class="container clearfix" style="position: fixed; left: 20px; top: 67px;">
<h1 style="position: relative; top: 17px; right: -75px;">CHATS</h1>
<div class="scrollable">
<ul class="list">
<a class="clearfix" href="#">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/chat_avatar_01.jpg" />
<div class="about">
<div class="name">Vincent Portr</div>
<div class="status">
online
</div>
</div>
</a>
<a class="clearfix" href="#">
<img src="https://s3-us-west-2.amazonaws.com/s.cdpn.io/195612/chat_avatar_02.jpg" />
<div class="about">
<div class="name">Aiden Chavez</div>
<div class="status">
offline
</div>
</div>
</a>
</ul>
</div>
</div>
<!--The Message chats-->
<!--The Consultors cards-->
<main class="page-content">
<div class="card">
<h1 class="subtitle">CONSULTORA FAMILIAR</h1>
<div class="content">
<h2 class="title">Marcela Santamaria</h2>
<p class="copy">Check out all of these gorgeous mountain trips with beautiful views of, you guessed it, the mountains</p><a class="btn" href="Marcela/">Contactar</a></div>
</div>
<div class="card">
<div class="content">
<h2 class="title">Coming Soon</h2>
<p class="copy">Más consultores vendrán pronto</p></div>
</div>
</main>
<!--The Consultors cards-->
<!--Back and help buttons-->
<a href="/home" class="home"><i class="fa fa-home"></i></a>
<a href="#" class="help"><i class="fa fa-question"></i></a>
<!--Back and help buttons-->
</body>
</html>
my models:
from django.db import models
from django.conf import settings
from django.db import models
from django.db.models import Q
class ThreadManager(models.Manager):
def by_user(self, user):
qlookup = Q(first=user) | Q(second=user)
qlookup2 = Q(first=user) & Q(second=user)
qs = self.get_queryset().filter(qlookup).exclude(qlookup2).distinct()
return qs
def get_or_new(self, user, other_username): # get_or_create
username = user.username
if username == other_username:
return None
qlookup1 = Q(first__username=username) & Q(second__username=other_username)
qlookup2 = Q(first__username=other_username) & Q(second__username=username)
qs = self.get_queryset().filter(qlookup1 | qlookup2).distinct()
if qs.count() == 1:
return qs.first(), False
elif qs.count() > 1:
return qs.order_by('timestamp').first(), False
else:
Klass = user.__class__
user2 = Klass.objects.get(username=other_username)
if user != user2:
obj = self.model(
first=user,
second=user2
)
obj.save()
return obj, True
return None, False
class Thread(models.Model):
first = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='chat_thread_first')
second = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='chat_thread_second')
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
objects = ThreadManager()
@property
def room_group_name(self):
return f'chat_{self.id}'
def broadcast(self, msg=None):
if msg is not None:
broadcast_msg_to_chat(msg, group_name=self.room_group_name, user='admin')
return True
return False
class ChatMessage(models.Model):
thread = models.ForeignKey(Thread, null=True, blank=True, on_delete=models.SET_NULL)
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='sender', on_delete=models.CASCADE)
message = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)
my consumers.py:
import asyncio
import json
from django.contrib.auth import get_user_model
from channels.consumer import AsyncConsumer
from channels.db import database_sync_to_async
from .models import Thread, ChatMessage
class ChatConsumer(AsyncConsumer):
async def websocket_connect(self, event):
print("connected", event)
other_user = self.scope['url_route']['kwargs']['username']
me = self.scope['user']
# print(other_user, me)
thread_obj = await self.get_thread(me, other_user)
self.thread_obj = thread_obj
chat_room = f"thread_{thread_obj.id}"
self.chat_room = chat_room
await self.channel_layer.group_add(
chat_room,
self.channel_name
)
await self.send({
"type": "websocket.accept"
})
# await asyncio.sleep(10)
async def websocket_receive(self, event):
# when a message is received from the websocket
print("receive", event)
front_text = event.get('text', None)
if front_text is not None:
loaded_dict_data = json.loads(front_text)
msg = loaded_dict_data.get('message')
user = self.scope['user']
username = 'default'
if user.is_authenticated:
username = user.username
myResponse = {
'message': msg,
'username': username,
}
await self.create_chat_message(user, msg)
# broadcast the message event to be send
await self.channel_layer.group_send(
self.chat_room,
{
"type": "chat_message",
"text": json.dumps(myResponse)
}
)
async def chat_message(self, event):
# sends the actual message
await self.send({
"type": "websocket.send",
"text": event['text']
})
async def websocket_disconnect(self, event):
# when the socket connects
print("disconnected", event)
@database_sync_to_async
def get_thread(self, user, other_username):
return Thread.objects.get_or_new(user, other_username)[0]
@database_sync_to_async
def create_chat_message(self, me, msg):
thread_obj = self.thread_obj
return ChatMessage.objects.create(thread=thread_obj, user=me, message=msg)
By looking at your models, in your views you can make a context and then in your messages room you can use that context with django template tag, to loop all the chat rooms of your user, try this:
all_rooms = Thread.objects.by_user(request.user)
context = {
'my_chats': all_rooms
}
this is an option I see that you try with your models