Search code examples
javascriptpythonflaskjinja2

Update and render a value from Flask periodically


I want to display my CPU usage dynamically. I don't want to reload the page to see a new value. I know how to get the CPU usage in Python. Right now I render a template with the value. How can I continually update a page with a value from Flask?

@app.route('/show_cpu')
def show_cpu():
    cpu = getCpuLoad()
    return render_template('show_cpu.html', cpu=cpu)

Solution

  • Using an Ajax request

    Python

    @app.route('/_stuff', methods= ['GET'])
    def stuff():
        cpu=round(getCpuLoad())
        ram=round(getVmem())
        disk=round(getDisk())
        return jsonify(cpu=cpu, ram=ram, disk=disk)
    

    Javascript

    function update_values() {
        $SCRIPT_ROOT = {{ request.script_root|tojson|safe }};
        $.getJSON($SCRIPT_ROOT+"/_stuff",
            function(data) {
                $("#cpuload").text(data.cpu+" %")
                $("#ram").text(data.ram+" %")
                $("#disk").text(data.disk+" %")
            });
    }
    

    Using Websockets

    project/app/views/request/websockets.py

    # -*- coding: utf-8 -*-
    
    # OS Imports
    import json
    
    # Local Imports
    from app import sockets
    from app.functions import get_cpu_load, get_disk_usage, get_vmem
    
    @sockets.route('/_socket_system')
    def socket_system(ws):
        """
        Returns the system informations, JSON Format
        CPU, RAM, and Disk Usage
        """
        while True:
            message = ws.receive()
            if message == "update":
                cpu = round(get_cpu_load())
                ram = round(get_vmem())
                disk = round(get_disk_usage())
                ws.send(json.dumps(dict(received=message, 
                    cpu=cpu, ram=ram, disk=disk)))
            else:
                ws.send(json.dumps(dict(received=message)))
    

    project/app/__init__.py

    # -*- coding: utf-8 -*-
    from flask import Flask
    from flask_sockets import Sockets
    
    
    app = Flask(__name__)
    sockets = Sockets(app)
    app.config.from_object('config')
    from app import views
    

    Using Flask-Websockets made my life a lot easier. Here is the launcher : launchwithsockets.sh

    #!/bin/sh
    
    gunicorn -k flask_sockets.worker app:app
    

    Finally, here is the client code: custom.js

    Note that I'm NOT using things like socket.io, that's why the code is long. This code also tries to reconnect to the server periodically, and can stop trying to reconnect on a user action. I use the Messenger lib to notify the user that something went wrong. Of course it's a bit more complicated than using socket.io but I really enjoyed coding the client side.