I'm trying to get server messages pushed out to the end user that's logged into our flask website.
I've done some research and it seems that the best solution is to use socket-io.
My attempts at this don't seem to be working, I must also indicate that my knowledge of javascript is very basic.
Any assistance / guidance will be highly appreciated.
See my code below:
python - app.py
from flask_socketio import SocketIO, emit
from flask import Flask, render_template, url_for, request
from time import sleep
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
app.config['DEBUG'] = True
# turn the flask app into a socketio app
socketio = SocketIO(app, async_mode=None, logger=True, engineio_logger=True)
@app.route('/', methods=['GET', 'POST'])
def index():
if request.method == 'POST':
if request.form['submit_button'] == 'Do Stuff':
# server doing things....
# the below method will make calls to emit socket messages
# based on actions / outcome of actions.
serverActions()
return render_template('index.html')
@socketio.on('connect')
def connect():
print('Client connected')
@socketio.on('display_message')
def displayMessage(message):
socketio.emit('newmessage', {'message': message})
socketio.sleep(2)
def serverActions():
# get connection to DB
message = "connecting to DB"
# show message to user on flask page
displayMessage(message)
# test successful connection to DB
message = "successfully connected to DB"
displayMessage(message)
# query the DB
message = "querying the DB"
displayMessage(message)
# update DB
message = "updating the DB"
displayMessage(message)
# etc......
if __name__ == '__main__':
socketio.run(app)
HTML - templates/index.html
<!DOCTYPE html>
<html>
<head>
<script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
<script src="static/js/application.js"></script>
</head>
<body>
<form method="POST">
<div>
<div>
<h1>Asynchronous Flask Communication</h1>
<p>Messages generated by the Flask server should appear below, asynchronously.</p>
</div>
</div>
<div>
<p>Asynchronous page updates will appear here:</p>
<div>
<input type="submit" value="Do Stuff" name="submit_button">
</div>
<div>
<h3>Server Messages:</h3>
<div id="message">
</div>
</div>
</div>
</form>
</body>
</html>
javascript - static/js/application.js
$(document).ready(function(){
//connect to the socket server.
var socket = io.connect('http://' + document.domain + ':' + location.port);
//receive message details from server
socket.on('display_message', function(msg) {
console.log("Received message" + msg.message);
message_string = '<p>' + msg.message + '</p>';
$('#message').html(message_string);
});
});
You emit
events that you listen for with on
event handler. Also I don't think it makes sense for your event listener display_message
to be inside a rest endpoint. Here is a solution with pypubsub
for convenience so you can easily subscribe for all events on the server. It can work without it too but here it is
server.py
from flask_socketio import SocketIO, emit
from flask import Flask, render_template, url_for, request
from time import sleep
from pubsub import pub
app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
app.config['DEBUG'] = True
# turn the flask app into a socketio app
socketio = SocketIO(app, async_mode=None, logger=True, engineio_logger=True)
def listener(arg1):
print('Function listener1 received:')
print(' arg1 =', arg1)
socketio.emit('newmessage',{'message':arg1})
pub.subscribe(listener, 'rootTopic')
@app.route('/', methods=['GET', 'POST'])
def index():
return render_template('index.html')
@app.route('/post', methods=['POST'])
def post():
pub.sendMessage('rootTopic', arg1='post')
@socketio.on('connect')
def connect():
pub.sendMessage('rootTopic', arg1='connected to socket')
print('Client connected')
if __name__ == '__main__':
socketio.run(app)
index.html
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<div id="message"></div>
<button id="btn">CLICK</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script>
$(document).ready(function(){
//connect to the socket server.
var socket = io.connect('http://' + document.domain + ':' + location.port);
$('#btn').on('click', function() {
fetch('http://' + document.domain + ':' + location.port + '/post', {method:"POST"})
})
//receive message details from server
socket.on('newmessage', function(msg) {
console.log("Received message" + msg.message);
message = '<p>' + msg.message + '</p>';
$('#message').append(message);
});
});
</script>
</body>
</html>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With