In our previous Python project tutorial, we have developed School Management System with Python, Flask and MySQL. In this tutorial, we will develop Online Web Chat using Flask and Python.
A web chat system is an online interface that allows to communicate directly with peoples in real time. Here, we will develop a web chat system using Flask web framework and Flask-SocketIO module that enables bi-directional communication between the server and the client using WebSockets. The WebSockets are a protocol that enables fast and efficient data transfer between the browser and the server, without polling or refreshing.
So let’s proceed with developing Online Web Chat project:
1. Project Setup and Module Installation
First we will create our project web-chat-app-python-flask using below command.
$ mkdir web-chat-app-python-flask
and moved to the project.
$ cd web-chat-app-python-flask
Then we will install required modules for our application. As we will develop a web based application, so we will install Flask micro framework module to create web application.
$ pip install Flask
As we will use Flask-SocketIO module in this project, so we will install this module:
$ pip install flask-socketio
2. Initialize Application
We will create project python file main.py and import required modules. We will create flask instance and also create SocketIO instance.
from flask import Flask, request, render_template, redirect, url_for, session from flask_socketio import SocketIO, join_room, leave_room, send from utils import getRoomCode app = Flask(__name__) app.config['SECRET_KEY'] = 'ABCDFRHGRPTY' socketio = SocketIO(app)
We run our app using the SocketIO
instance with socketio.run(app, debug=True)
instead of using the Flask instance.
if __name__ == '__main__': socketio.run(app, debug=True)
3. Create Web Chat Home
We will create route to load home page home.html
for our chatroom app. We will handle for submit create chatroom or join chatroom.
rooms = {} @app.route('/', methods=["GET", "POST"]) def home(): session.clear() if request.method == "POST": name = request.form.get('name') create = request.form.get('create', False) code = request.form.get('code') join = request.form.get('join', False) if not name: return render_template('home.html', error="Name is required", code=code) if create != False: room_code = getRoomCode(6, list(rooms.keys())) new_room = { 'members': 0, 'messages': [] } rooms[room_code] = new_room if join != False: if not code: return render_template('home.html', error="Please enter a room code to enter a chat room", name=name) if code not in rooms: return render_template('home.html', error="Room code invalid", name=name) room_code = code session['room'] = room_code session['name'] = name return redirect(url_for('room')) else: return render_template('home.html')
We will create home.html
and design home page html.
{% extends 'base.html' %} {% block content %} <div id="home-container"> <h1 id="home-header">Online Web Chat</h1> {% if error %} <p id="error">{{error}}</p> {% endif %} <form method="post" id="chat-widget-home"> <div id="name-input"> <label for="name"></label> <input type="text" id="name" name="name" placeholder="Enter name" value="{{name}}" /> </div> <div> <label for="code" id="code-label"></label> <input type="text" id="code" name="code" placeholder="Enter code" value="{{code}}" /> <button type="submit" id="join" name="join">Join</button> </div> <hr /> <button type="submit" id="create" name="create">Create Room</button> </form> </div> {% endblock %}
4. Create Chat Room
We will route for room and load room.html
template to load chat room page. We will display chat and also handle message send functionality.
@app.route('/room') def room(): room = session.get('room') name = session.get('name') if name is None or room is None or room not in rooms: return redirect(url_for('home')) messages = rooms[room]['messages'] return render_template('room.html', room=room, user=name, messages=messages)
We will create room.html
template and create html for room page. We will also includes the SocketIO connection JavaScript code on the client side to send message.
{% extends 'base.html' %} {% block content %} <div id="room-container"> <h1 id="home-header">Online Web Chat</h1> <div id="room-subsection"> <span id="room-code-display">Room Code: <span>{{room}}</span></span> <span><a href="/" id="leave-chat-btn">Leave</a></span> </div> <div id="chat-room-widget"> <div id="msgs-container"> <ul id="messages"></ul> </div> <div id="message-box"> <input type="text" placeholder="Enter your message" id="message-input" name="message" /> <button type="submit" id="send-btn" onclick="sendMessage()">Send</button> </div> </div> <script type="text/javascript"> var socketio = io(); socketio.on("message", function (message) { createMessage(message.message, message.sender); }); function createMessage(message, sender) { var messages = document.getElementById("messages"); if (sender === "") { content = ` <p class="member-activity">${message}</p> `; } else { var senderIsUser = "{{user}}" === sender; var content = ` <li class="message-item ${ senderIsUser ? "self-message-item" : "peer-message-item" }"> <p>${message}</p> <small class="${ senderIsUser ? "muted-text" : "muted-text-white" }">${new Date().toLocaleString()}</small> </li> `; } messages.innerHTML += content; } function sendMessage() { var msgInput = document.getElementById("message-input"); if (msgInput.value === "") return; var msg = msgInput.value; socketio.emit("message", { message: msg }); msgInput.value = ""; } </script> {% for message in messages %} <script type="text/javascript"> createMessage("{{message.message}}", "{{message.sender}}"); </script> {% endfor %} </div> {% endblock %}
5. Handle Web Websocket Events
We will also handle websockets events at server side. Here we will handle connect
, message
and disconnect
events.
So first we will handle connect
that fired when a client connects to the server. It uses the room id and user name passed by the client to let the user join the chat room, then redirects the user to the chat room page with the message.
@socketio.on('connect') def handle_connect(): name = session.get('name') room = session.get('room') if name is None or room is None: return if room not in rooms: leave_room(room) join_room(room) send({ "sender": "", "message": f"{name} has entered the chat" }, to=room) rooms[room]["members"] += 1
We will handle message
event that fired when the client or server sends a message to each other. This event handler expects a data payload where it retrieves the user’s message. It will then send the message to the chat room for everyone to see in rooms.
@socketio.on('message') def handle_message(payload): room = session.get('room') name = session.get('name') if room not in rooms: return message = { "sender": name, "message": payload["message"] } send(message, to=room) rooms[room]["messages"].append(message)
We will also handle disconnect
event that fired when user leaves a chat room. This event handler just removes the user from the chat room and lets everyone knows the user has left by sending a message event to the chat room.
@socketio.on('disconnect') def handle_disconnect(): room = session.get("room") name = session.get("name") leave_room(room) if room in rooms: rooms[room]["members"] -= 1 if rooms[room]["members"] <= 0: del rooms[room] send({ "message": f"{name} has left the chat", "sender": "" }, to=room)
In this tutorial, you have learned how to use SocketIO technology in Python using Flask and Flask-SocketIO. This is a simple web chat app, you can try to develop real-time bi-directional communication with SocketIO in your future projects.
You can download the complete source code of project from the Download link below.