Django chat app sorted messages by datetime

i have a chat and Message Model. How can i sort my Chat with the creation_date of Message example:consider that i am in two chats(A and B): i want that everytime i receive a message from B so that B should be the bottom of A and when i receive a message from A so that A should be the bottom of B. I've spent a lot of time to do this but there was no success.

Models.py

 `class Chat(models.Model):
creation_date = models.DateField(default=timezone.now)
id = models.AutoField(primary_key=True)
content = models.TextField()
sender = models.ForeignKey(
    BasicUserProfile,
    on_delete=models.CASCADE,
    blank=True,
    null=True,
    related_name="sender"
)
reciever = models.ForeignKey(
    BasicUserProfile,
    on_delete=models.CASCADE,
    blank=True,
    null=True,
    related_name="reciever"
)
class Meta:
    ordering = ["-creation_date"]
def __str__(self):
    return "chat: " + str(self.sender)`

views.py

# admin user session pop
# admin user session pop
# Deleting any sessions regarding top-tier type of users

# Get the current users
current_basic_user = get_current_user(request, User, ObjectDoesNotExist)

current_basic_user_profile = get_current_user_profile(
    request,
    User,
    BasicUserProfile,
    ObjectDoesNotExist
)




# Topics to follow
topics_to_follow = get_topics_to_follow(Topic, ObjectDoesNotExist, random)

# Who to follow box cells
who_to_follow = get_who_to_follow(
    BasicUserProfile
)

# Get the current followings
try:
    current_followings = Follower.objects.filter(
        follower=current_basic_user_profile
    )
except ObjectDoesNotExist:
    current_followings = None

# Get the current text reciever (user)
try:
    current_reciever_user = User.objects.get(username=username)
except ObjectDoesNotExist:
    current_reciever_user = None

try:
    current_reciever = BasicUserProfile.objects.get(
        user=current_reciever_user
    )
except ObjectDoesNotExist:
    current_reciever = None

if current_reciever_user == None:
    return HttpResponseRedirect("/")


# Getting the chat history feed

try:
    chat_records_self = Chat.objects.filter(
    sender=current_basic_user_profile,
    reciever=current_reciever
    )
    chat_records_reciever = Chat.objects.filter(
    sender=current_reciever,
    reciever=current_basic_user_profile
    )
except ObjectDoesNotExist:
    chat_records_self = None
    chat_records_reciever= None
chat_history_feed = []
print(chat_records_self)
print(chat_records_reciever)

#Combine chat records from both sender and receiver

combined_chat_records = list(chat_records_self) + list(chat_records_reciever)

#Sort the combined chat records based on the creation date of the messages
sorted_chat_history_feed = sorted(combined_chat_records, key=attrgetter('creation_date'), reverse=True)

#Pass the sorted chat history feed to the template

# Chat text from processing
if request.method == "POST":
    if request.POST.get("chat_send_submit_btn"):
        chat_content = request.POST.get("chat_content")
        new_message = Chat(
        content=chat_content,
        sender=current_basic_user_profile,
        reciever=current_reciever,
        )
        new_message.save()
        chat_history_feed.append(chat_content)  # Adding the message to chat history feed
        return HttpResponseRedirect("/chat/"+current_reciever_user.username+"/",{"chat_history_feed":chat_history_feed})
    
context = {
    "current_basic_user": current_basic_user,
    "current_basic_user_profile": current_basic_user_profile,
    "who_to_follow": who_to_follow,
    "chat_history_feed": chat_history_feed,
    "chat_records_self": chat_records_self,
    "chat_records_reciever": chat_records_reciever,
    "topics_to_follow": topics_to_follow,
    "current_followings": current_followings,
    "current_reciever": current_reciever,
    'chat_history_feed':sorted_chat_history_feed
}

if current_basic_user == None:
    return HttpResponseRedirect("/auth/login/")
else:
    return render(request, "chat/single.html", context)

single.html

   ` <div id="chat-right-middle-box">
  <div id="chat-self-box">
      {% for chat_record in chat_history_feed %}
              <p> {{chat_record.content}}</p>
              {% endfor %}

  </div>`

I tried to seperate and create a new model instead of chat, but it was not a good idea.

at first:

To return obj=None on ObjectDoesNotExist Django have special methods first/last:

Instead of this:

try:
    current_reciever_user = User.objects.get(username=username)
except ObjectDoesNotExist:
    current_reciever_user = None

use this:

current_reciever_user = User.objects.filter(username=username).first()

At second. It is better to sort on Database level, not in python:

from django.db.models import Case, Value, When
    ....
    # define which chat you want to see
    chat = ??? 
    # define if chat=A, sender=A - priority 1
    # define if chat=B, sender=A - priority 2
    # define if chat=A, sender=B - priority 2
    # define if chat=B, sender=B - priority 1

    priority = Case(
        When(Q(sender=A), then=Value(int(chat==A or 2))),
        When(Q(sender=B), then=Value(int(chat==B or 2))),
        then=Value(3)),
    )
    # define queryset
    chats = Chat.objects.all() 

    # add filter by sender
    chats = chats.filter(
Q(sender=current_basic_user_profile) | Q(sender=current_reciever))

    # add filter by receiver
    chats = chats.filter(Q(receiver=current_basic_user_profile) | Q(receiver=current_reciever))
    # right now you have all wanted chats.

    # add priority calculation, .alias() is like .annotation()
    chats = chats.alias(priority_order=priority_order)

    # Finally add ordering:
    chats = chats.order_by("-creation_date", "priority")

If i understand correct your tack - you get for chat A:

on 20.05.2023
    all A, 
    all B,
on 19.05.2023
    all A,
    all B, 
etc.

And you get for chat B:

on 20.05.2023 
    all B, 
    all A, 
19.05.2023 
    all B, 
    all A, 
etc.

More info about Case When in django: https://docs.djangoproject.com/en/5.0/ref/models/conditional-expressions/#conditional-expressions

More info about alias: https://docs.djangoproject.com/en/5.0/ref/models/querysets/#alias

Good luck!

Back to Top