Flask and SocketIO - How to Use it Together
Learn how to use Flask with SocketIO
Socket.IO is a library that enables real-time, bidirectional, and event-driven communication between a client and a server. It is built on top of the WebSocket protocol, which allows for fast and simultaneous communication between the server and the browser.
- 👉 Flask SocketIO Sample - published on
GitHub
- 👉 Free Support via Email & Discord
Socket.IO provides additional features like fallback options for HTTP long-polling and automatic reconnection, enhancing the reliability and versatility of real-time applications.
Here are the
key features of Socket.IO
:
Real-time communication: Socket.IO enables instantaneous and bidirectional data exchange between web clients and servers, eliminating the need for page refreshes.
Event-driven: Socket.IO operates on an event-driven model, allowing clients and servers to communicate by sending and receiving events. This simplifies the development of complex real-time applications.
Reliability: Socket.IO ensures a reliable connection, even in the presence of network disruptions. It automatically attempts to reconnect if the connection is lost.
Scalability: Socket.IO is designed to handle a large number of concurrent connections, making it scalable for applications with high traffic.
Socket.IO finds application in various scenarios, including:
Chat applications: Socket.IO is commonly employed for creating chat apps, enabling real-time communication between users.
Multiplayer games: Socket.IO facilitates real-time player interactions and synchronization, making it suitable for building multiplayer games.
Live streaming applications: Socket.IO can be utilized to construct live streaming platforms, enabling users to watch live streams in real-time.
If you're looking to develop real-time web applications, Socket.IO is an excellent choice. It offers simplicity, reliability, and efficiency, and is well-supported across different browsers and devices.
✅ Using Socket.IO with Flask​
To use Socket.IO with Flask, we will utilize the flask-socketio
package. In this tutorial, we will demonstrate how Socket.IO can update a card on a Flask dashboard.
We will utilize the Flask dashboard called Flask Gradient Able.
Setting up Flask application​
Clone the repository into your machine
$ git clone https://github.com/app-generator/sample-flask-socketio
$ cd sample-flask-socketio
sample-flask-socketio$
Create a virtual environment and activate the environment to isolate the development environment from your global Python installation
sample-flask-socketio$ virtualenv venv
sample-flask-socketio$
sample-flask-socketio$ source venv/bin/activate # on Linux/machine
sample-flask-socketio$
sample-flask-socketio$ .\venv\Scripts\activate # on Windows
Install the project dependencies using pip
(venv) sample-flask-socketio$ pip install -r requirements.txt
Run the flask application to ensure it is properly setup using the command
(venv) sample-flask-socketio$ flask run
Visit http://127.0.0.1:5000
on your browser.
Create an account to view the homepage of the application. You can stop the flask server using Ctrl + c
.
Integrating Socket.IO
with Flask
​
To integrate Socket.IO into a Flask application, we will utilize the flask-socketio
package. This package empowers Flask applications to harness the capabilities and advantages of SocketIO.
- Install
flask-socketio
package using the command
(venv) sample-flask-socketio$ pip install flask-socketio
- Create a file in the
apps
folder namedevents.py
, this file will be used to create the socketio object and will also contain events that will be handled using socketio
# apps/events.py
from flask_socketio import SocketIO,
socketio = SocketIO()
@socketio.on('connect')
def connect_event():
print('Client connected')
- Add Socket.IO to the application by making the following changes to
apps/__init__.py
# apps/__init__.py
...
from apps.events import socketio
...
def create_app(config):
app = Flask(__name__)
...
socketio.init_app(app)
return app
To ensure that the events to be handled by SocketIO are loaded into the socketio
object and registered with the Flask app,
we import socketio
from app/events.py
and initialize it with the Flask app using socketio.init_app(app)
.
This ensures that the event handlers are properly integrated with the SocketIO functionality.
- Make the following changes to
run.py
# run.py
...
from apps import socketio # <-- NEW
...
if __name__ == "__main__":
socketio.run(app) # <-- UPDATED
- Add SocketIO script tag to
apps/templates/home/index.html
, this loads the Socket.IO library and establishes a connection.
<!-- apps/templates/home/index.html -->
...
<body>
...
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.0.1/socket.io.js"></script>
<script>
const socket = io();
socket.on('connect', function(data) {
console.log('Socket.IO is connected!!!')
});
</script>
</body>
To ensure that a connection can be established by your application:
- run the flask app using
flask run
from your terminal. - Open
http://127.0.0.1:5000
on your browser. - Log in to the application
- Open the developers console using
Ctrl + Shift + I
orCommand + Option + i
(on Mac).
Emitting and Receiving Events​
SocketIO sends messages as events, allowing for communication between the server and client in both directions.
The server can send events to the client, and vice versa. SocketIO includes default events such as connect
and message
, but we can create custom events and handle them on both the client and server-side.
Next, we will be sending a message from the client to the server and then we will print that message on the terminal.
- Make the following change to
apps/templates/home/base.html
<!-- apps/templates/home/index.html -->
...
<script type="text/javascript" charset="utf-8">
const socket = io();
socket.on('connect', function(data) {
console.log('Socket.IO is connected!!!')
});
socket.send('The send method is used to initiate the message event');
</script>
- Add the following line of code to
apps/events.py
# apps/events.py
...
@socketio.on('message')
def handle_message(data):
print('This is a message:', data)
Refresh your browser and check your Python terminal. You will observe that the message from the client is printed on the Python terminal.
Creating custom events​
In addition to having default events, we can create custom events to tailor our code to various situations.
The key distinction between messages and custom events lies in how they are triggered. To trigger a custom event, we utilize the emit
method, as we will see shortly.
- Create a custom event called
new event
by adding the code below toapps/events.py
# apps/events.py
...
@socketio.on('new event')
def handle_new_event(data):
print('A new event was emitted from the client containing the following payload', data)
socketio.emit('server event', {'data': 'This is how you trigger a custom event from the server-side'})
- Add the code below to
apps/templates/home/index.html
to receive and send events from the client side
<!-- apps/templates/home/index.html -->
<script type="text/javascript" charset="utf-8">
...
socket.emit('new event', 'The data can be an object or a string');
socket.on('server event', function(data) {
console.log(data);
});
</script>
After making the changes to the code as mentioned, please refresh your browser and examine both your browser console and the Python terminal. You will observe the events being handled by both sides of the application.
✅ Real-Time Updates in Flask​
Using SocketIO, we will implement real-time updates in our Flask application. The details of a card on our dashboard will be updated whenever a new entry is added to our database.
- First we will be creating a
Sales
table using schema. Create a new file inapps/home
namedmodel.py
and add the following code
# apps/home/model.py
from apps import db
class Sales(db.Model):
__tablename__ = 'Sales'
id = db.Column(db.Integer, primary_key=True)
product = db.Column(db.String(64))
amount = db.Column(db.String(64))
status = db.Column(db.Enum('Completed', 'Not Completed'), default='Not Completed')
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
def __repr__(self):
return str(self.product)
def save(self):
db.session.add(self)
db.session.commit()
- Make the following update to
apps/__init__.py
so the newSales
table can be created when the flask server starts up.
# apps/__init__.py
...
def register_extensions(app):
from apps.home.model import Sales # <--- NEW
db.init_app(app)
...
Please restart the Flask server and visit the homepage. This action will result in the addition of the Sales
table to the database.
Implementing real-time updates using Socket.IO​
To implement real-time updates on the application, we will create a new route that allows the addition of entries to the database. Once an entry is added, we will update the card components on the homepage.
- We will be creating a route for adding new entries to the
Sales
table. Add the code below toapps/home/routes.py
# apps/home/routes.py
...
from apps.home.model import Sales
from flask_socketio import emit
from sqlalchemy.sql import func, funcfilter
from apps import db
...
@blueprint.route('/sales', methods=['POST'])
def add_sale():
print(request.form)
sale = Sales(**request.form)
sale.save()
query = db.session.query(func.count(Sales.product), func.count(Sales.product).filter(Sales.status == 'Completed'))
result = query.first()
data = {'total-sales': result[0], 'sales-completed': result[1]},
emit('sales', data, broadcast=True, namespace='/')
return jsonify(dict(**request.form), 200)
Now that we have a route that can add products to the sales database, we emit a sales
event that is broadcasted to all clients connected to the server.
While the Flask server is running, open another terminal and execute the following command to add entries to your database using the route:
curl -X POST -F product=product-name -F amount=product-amount -F status=Completed http://localhost:5000/sales
NOTE: You can replace product-name
with the value you want to add to the database, and product-amount
with whatever number you choose. -F status=Completed
can be removed to create an entry with a status of Not Completed
.
- Let's add the following line of code to apps/templates/home/index.html to listen for the sales event emitted from the route we created earlier
<!-- apps/templates/home/index.html -->
...
<script type="text/javascript" charset="utf-8">
...
socket.on('sales', function(data) {
// function to be carried out when the event is emitted will go here
console.log(data);
});
</script>
You can try adding entries to your database using the command mentioned earlier. Upon checking your browser console, you will observe that the data sent using curl
is displayed in the console.
Updating the UI in response to Events​
For the final part of our tutorial on using SocketIO to achieve real-time updates in our application, we will write the logic to update the Orders received
card on the homepage.
- Let's make the following changes to
app/home/routes.py
to add a context that sends the numver of sales and sales completed to the homepage. These values will be used to update theOrders received
card:
# apps/home/routes.py
...
@blueprint.route('/index')
@login_required
def index():
query = db.session.query(func.count(Sales.product), func.count(Sales.product).filter(Sales.status == 'Completed'))
sales = query.first() # returns -> (total sales, sales completed)
return render_template('home/index.html', segment='index', sales=sales) # UPDATED
- Let's make the following changes to
apps/templates/home/index.html
to retrieve the orders received from the database
<!-- apps/templates/home/index.html -->
...
<div class="card-body"> <!-- Line 18 -->
<h6 class="text-white">Orders Received</h6>
<h2 class="text-end text-white"><i class="feather icon-shopping-cart float-start"></i><span class="total-sales">{{sales[0]}}</span></h2> <!-- Updated -->
<p class="m-b-0">Completed Orders<span class="float-end sales-completed">{{sales[1]}}</span></p> <!-- Updated -->
</div>
...
NOTE Take note of the added id
attribute inside the span
tags
- Now let's write the logic to update the cards when a POST request is sent to
http://localhost:5000/sales
. We'll make the following changes toapps/templates/home/index.html
...
<script type="text/javascript" charset="utf-8">
...
socket.on('sales', function(data) {
// console.log(data);
const total_sales = document.getElementById('total-sales');
const sales_completed = document.getElementById('sales-completed');
total_sales.innerHTML = data['total-sales'];
sales_completed.innerHTML = data['sales-completed'];
});
</script>
...
When the server emits the sales
event, it triggers the function responsible for updating the card elements on the homepage.
This function is automatically executed in response to the event and is responsible for handling the necessary updates to the card components based on the received data.
✅ In Summary​
In this tutorial, we learned how to use Socket.IO with Flask to create real-time updates in web applications. We started by setting up a simple Flask application, and then we integrated Socket.IO with Flask. We then learned how to emit and receive events between the client and server. Finally, we implemented real-time updates using Socket.IO, and we updated a card or component on the Flask dashboard in response to events.
This tutorial has shown how easy it is to use Socket.IO with Flask to create real-time updates in web applications. Socket.IO is a powerful tool that can be used to create a variety of real-time applications, such as chat applications, multiplayer games, and stock tickers.
✅ Resources​
- 👉 Access AppSeed for more starters and support
- 👉 Deploy Projects on Aws, Azure and DO via DeployPRO
- 👉 Create landing pages with Simpllo, an open-source site builder
- 👉 Build apps with Django App Generator (free service)