Django filter query to get chat messages among two friends?

I am trying to create a chat api, i have structured the messages model to look like this


class ChatMessage(models.Model):
    user = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name="user")
    sender = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name="sender")
    reciever = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, related_name="reciever")
    message = models.CharField(max_length=10000000000)
    is_read = models.BooleanField(default=False)
    date = models.DateTimeField(auto_now_add=True)

Now i am trying to write the API view to get all messages that belongs only to me and the person that i am chatting with.

Let me elaborate: Let’s say Destiny is texting John, there would definitely be alot of messages that have been sent between me (Destiny) and the user (John), so i want to get all that text.

This is the view that i have written to do this

class GetMessages(generics.ListAPIView):
    serializer_class = MessageSerializer
    
    def get_queryset(self):
        sender_id = self.kwargs['sender_id']
        reciever_id = self.kwargs['reciever_id']
        messages =  ChatMessage.objects.filter(sender=sender_id, reciever=reciever_id)
        return messages

urls

    path("api/get-messages/<sender_id>/<reciever_id>/", views.GetMessages.as_view()),

This is what this view returns

## url - http://127.0.0.1:8000/api/get-messages/2/1/
[
    {
        "id": 2,
        "sender": 2,
        "reciever": 1,
        "message": "Hey Destiny",
        "is_read": false
    }
]

if i swap the sender_id and reciever_id, this is the response i get

# url - http://127.0.0.1:8000/api/get-messages/1/2/
[
    {
        "id": 1,
        "sender": 1,
        "reciever": 2,
        "message": "Hello Sammy",
        "is_read": false
    },
    {
        "id": 3,
        "sender": 1,
        "reciever": 2,
        "message": "This is another message for you sammy",
        "is_read": false
    }
]

what i want is this, when i pass in the id of the sender (1) and id of the reciever (2) in the url, i want to get a response like this, which is all the conversaion that this two folks have had.

[
    {
        "id": 1,
        "sender": 1,
        "reciever": 2,
        "message": "Hello Sammy",
        "is_read": false
    },
    {
        "id": 2,
        "sender": 2,
        "reciever": 1,
        "message": "Hey Destiny",
        "is_read": false
    },
    {
        "id": 3,
        "sender": 1,
        "reciever": 2,
        "message": "This is another message for you sammy",
        "is_read": false
    }
]

Some images



There’s one more condition that might need to be addressed. Is there any possibility for person to send a message to themself? In other words, do we need to be concerned about the case where sender_id == receiver_id?

If not, you can do this most easily with a couple of in clauses -
ChatMessage.objects.filter(sender__in=[sender_id, receiver_id], receiver__in=[sender_id, receiver_id])

There are other ways of writing this as well. You could also do this as a pair of Q clauses:
ChatMessage.objects.filter(Q(sender=sender_id, receiver=receiver_id)|Q(sender=receiver_id, receiver=sender_id))
This query will not include messages where sender==receiver, except for those cases where the query is issued with sender_id==receiver_id.

1 Like

This fixed it for me, thanks a lot.