I am creating a live chart that dynamically updates itself. I am taking a tuple of (current time, random integer) for my chart from a dummy database, sender.py
. Here is the code for sender.py
-
import time
import random
import json
from datetime import datetime
def get_coordinates():
while True:
json_data = json.dumps(
{
'time' : datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'value' : random.random() * 1000
})
yield "data:{}\n\n".format(json_data)
time.sleep(1)
I share this data to the route, /chart-data
, made in app.py
-
import os
from flask import Flask, render_template, Response
from sender import get_coordinates
app = Flask(__name__)
@app.route('/chart-data', methods = ['POST'])
def chart_data():
get_coordinates()
return Response(get_coordinates())
@app.route("/")
def index():
return render_template('data.html')
I upload json_data
from sender.py
to the route /chart-data
and want to get this in data.html
. Here is the .html file (I am trying to retrieve this data in $.ajax()
method ) -
...
<body>
<canvas id = 'myChart' width = "900" height = "400"></canvas>
<script>
var intervalID = setInterval(update_values, 1000);
var x_axis = 0;
var y_axis;
function update_values() {
$.ajax({
url: '/data',
type: 'GET',
success: function(result) {
//want to get x-axis and y-axis from sender.py
},
})
x_axis = x_axis 1;
myChart.data.labels.push(x_axis);
myChart.data.datasets.forEach((datasets) => {
datasets.data.push(y_axis);
});
myChart.update();
};
...
</script>
</body>
CodePudding user response:
Using a generator to stream data continuously does not make sense in this context. A possible solution is to get the current data with regular AJAX requests.
The following simple example shows you how to create a dynamically updating chart.
The application consists of two traditional endpoints. The former serves the actual page while the latter provides the data. With each request, additional data is generated and delivered in JSON format.
from flask import (
Flask,
jsonify,
render_template
)
from datetime import datetime
import random
app = Flask(__name__)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/data')
def data():
return jsonify({
'time': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
'value': random.randint(0, 1000)
})
Within the page, data is obtained from the server at regular intervals using the Fetch API. The data obtained is added to the chart. If there are already more than 10 data records, the oldest ones will be removed.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Index</title>
</head>
<body>
<div>
<canvas id="myChart" width="900" height="400"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script type="text/javascript">
(function(url) {
const limit = 9;
const canvas = document.getElementById('myChart');
const chart = new Chart(canvas, {
type: 'line',
data: {
labels: [],
datasets: [{
label: 'MyDataset',
data: []
}]
},
options: {
scales: {
yAxis: {
max: 1000,
min: 0
}
}
}
});
setInterval(async () => {
const data = await fetch(url).then(resp => resp.ok && resp.json());
if (data) {
const { time, value } = data;
const overflow = chart.data.labels.length - limit;
if (overflow > 0) {
chart.data.labels.splice(0, overflow);
chart.data.datasets[0].data.splice(0, overflow);
}
chart.data.labels.push(time);
chart.data.datasets[0].data.push(value);
chart.update();
}
}, 1000);
})({{ url_for('data') | tojson }});
</script>
</body>
</html>