In this Series of article we will learn how we can create personal chat application or whatsapp clone in django using channels and websockets.
For detailed video tutorial – click here
This is the part 2 of the series, so make sure you subscribe to the news-letter to get the notification about the next part and also make sure to watch youtube tutorial for easier understanding.
part 1 of article series
As we have successfully created the basic layout of the project, in this article we will create our first consumer for sending message via django-channels.
If you want to know how to integrate channels in django – Refer here.
Creating Consumer
After integrating django-channels, make this necessary configuration on asgi.py file located in a project folder.
""" ASGI config for whatsapp_clone project. It exposes the ASGI callable as a module-level variable named ``application``. For more information on this file, see https://docs.djangoproject.com/en/3.0/howto/deployment/asgi/ """ import os from django.core.asgi import get_asgi_application from django.urls import path from channels.routing import ProtocolTypeRouter, URLRouter from channels.auth import AuthMiddlewareStack from chats.consumers import PersonalChatConsumer os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'whatsapp_clone.settings') application = get_asgi_application() application = ProtocolTypeRouter({ 'websocket': AuthMiddlewareStack( URLRouter([ path('ws/<int:id>/', PersonalChatConsumer) ]) ) })
We have not created our consumer yet, so create a file called consumers.py in your app.
import json from channels.generic.websocket import AsyncWebsocketConsumer from channels.db import database_sync_to_async from chats.models import ChatModel class PersonalChatConsumer(AsyncWebsocketConsumer): async def connect(self): my_id = self.scope['user'].id other_user_id = self.scope['url_route']['kwargs']['id'] if int(my_id) > int(other_user_id): self.room_name = f'{my_id}-{other_user_id}' else: self.room_name = f'{other_user_id}-{my_id}' self.room_group_name = 'chat_%s' % self.room_name await self.channel_layer.group_add( self.room_group_name, self.channel_name ) await self.accept() async def receive(self, text_data=None, bytes_data=None): data = json.loads(text_data) message = data['message'] username = data['username'] await self.save_message(username, self.room_group_name, message) await self.channel_layer.group_send( self.room_group_name, { 'type': 'chat_message', 'message': message, 'username': username, } ) async def chat_message(self, event): message = event['message'] username = event['username'] await self.send(text_data=json.dumps({ 'message': message, 'username': username })) async def disconnect(self, code): self.channel_layer.group_discard( self.room_group_name, self.channel_name ) @database_sync_to_async def save_message(self, username, thread_name, message): ChatModel.objects.create( sender=username, message=message, thread_name=thread_name)
In this we have implemented three basic function of django-channels and a function to save messages in a database.
Now we just have to setup websockets to get and send message to our consumer for broadcasting to other memeber in a groups.
// chat.js const id = JSON.parse(document.getElementById('json-username').textContent); const message_username = JSON.parse(document.getElementById('json-message-username').textContent); const socket = new WebSocket( 'ws://' + window.location.host + '/ws/' + id + '/' ); socket.onopen = function(e){ console.log("CONNECTION ESTABLISHED"); } socket.onclose = function(e){ console.log("CONNECTION LOST"); } socket.onerror = function(e){ console.log("ERROR OCCURED"); } socket.onmessage = function(e){ const data = JSON.parse(e.data); if(data.username == message_username){ document.querySelector('#chat-body').innerHTML += `<tr> <td> <p class="bg-success p-2 mt-2 mr-5 shadow-sm text-white float-right rounded">${data.message}</p> </td> </tr>` }else{ document.querySelector('#chat-body').innerHTML += `<tr> <td> <p class="bg-primary p-2 mt-2 mr-5 shadow-sm text-white float-left rounded">${data.message}</p> </td> </tr>` } } document.querySelector('#chat-message-submit').onclick = function(e){ const message_input = document.querySelector('#message_input'); const message = message_input.value; socket.send(JSON.stringify({ 'message':message, 'username':message_username })); message_input.value = ''; }
And that’s all we have to do for making Personal chat consumer.
Cheers!!!
Thanks for reading.