Search code examples
pythonflaskflask-sockets

Emit websocket message from a view


I am playing around with websockets in order to see if I can replace polling updates to a project. I am using Flask-Sockets and I want to emit an update through a Flask view.

For example

from flask import Flask
from flask_sockets import Sockets

app = Flask(__name__)
sockets = Sockets(app)

@sockets.route('/echo')
def echo_socket(ws):
    while True:
        message = ws.receive()
        ws.send(message)

@app.route('/')
def hello():
    # here I want to emit a message like ws.send(message)
    return 'Hello World!'

I looked around and I didnt find anything similar. Is this thing possible?


Solution

  • THIS IS VERY VERY SIMPLE DEMO EXAMPLE

    In the below example, on every 2 seconds, the server send message to the client with updated count. First parameter of emit function tells which function to call on client side.

    app.py

    from flask import Flask, render_template
    from flask_socketio import SocketIO, emit
    
    
    app = Flask(__name__)
    app.config['SECRET_KEY'] = 'secret!'
    socketio = SocketIO(app)
    thread = None
    
    
    def background_thread():
        count = 0
        while True:
            socketio.sleep(2)
            count += 1
            socketio.emit('my_response',
                          {'data': 'Message from server', 'count': count},
                          namespace='/test')
    
    
    @app.route('/')
    def index():
        return render_template('index.html')
    
    
    @socketio.on('connect', namespace='/test')
    def test_connect():
        global thread
        if thread is None:
            thread = socketio.start_background_task(target=background_thread)
        emit('my_response', {'data': 'Connected', 'count': 0})
    
    
    if __name__ == '__main__':
        socketio.run(app, debug=True, host='0.0.0.0', port=5050)
    

    On your client side you will have to use this. In this example I have included CDN. Similarly for demo purpose I have used jquery.

    templates/index.html

    <!DOCTYPE HTML>
    <html>
    <head>
        <title>Flask-SocketIO Test</title>
        <script type="text/javascript" src="//code.jquery.com/jquery-1.4.2.min.js"></script>
        <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.5/socket.io.min.js"></script>
        <script type="text/javascript" charset="utf-8">
            $(document).ready(function() {
                namespace = '/test';
                var socket = io.connect(location.protocol + '//' + document.domain + ':' + location.port + namespace);
                // This will be called by server.
                // Anonymous function will be executed and span with id "view" will be updated
                socket.on('my_response', function(msg) {
                    $('span#view').text(msg.count);
                });
            });
        </script>
    </head>
    <body>
        <h1>Flask-SocketIO Simple Example</h1>
        <p>Counter at server: <span id="view"></span></p>
    </a>
    </body>
    </html>
    

    When you run this using python app.py, and visit http://127.0.0.1:5050, then you should see the sockets in action.

    A working version of the demo is available here