Reputation: 252
I am trying to create an interactive chart for a web app with data from python script.
The error is data from the python code is not transferred or updated on the chart.js script and not output on the html.
The flow of the 3 scripts: labels and data from python, goes into the chart.js to render the bar-chart and is output on the html
When I change Africa (data point) from 2447 to 5578, the chart is not updated. I am not sure if the issue is transferring from python or rendering the chart.
Python
from flask import Flask,render_template
app = Flask(__name__)
@app.route("/")
def result():
labels = ["Africa", "Asia", "Europe", "Latin America", "North America"]
data = [5578,5267,734,784,433]
return render_template("result.html", labels=labels, data=data)
if __name__ == '__main__':
app.debug = True
app.run()
script1.js
new Chart(document.getElementById("bar-chart"), {
type: 'bar',
data: {
labels: "{{labels}}",
datasets: [
{
label: "Population (millions)",
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
data: "{{data }}"
}
]
},
options: {
legend: { display: false },
title: {
display: true,
text: 'Predicted world population (millions) in 2050'
}
}
});
HTML
<!DOCTYPE html>
<html>
<head>
<title>New</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js">
</script>
</head>
<body>
<h1>Test</h1>
<div class="wrapper">
<canvas id="bar-chart" width="800" height="450"></canvas>
</div>
<script src="{{ url_for('static', filename='script1.js') }}"></script>
</body>
</html>
Upvotes: 1
Views: 7911
Reputation: 436
You may pass the data on a list (with render_template) and retrieve it on html with:
labels: [{% for item in families %}
"{{ item }}",
{% endfor %}]
Upvotes: 0
Reputation: 123
data:JSON.parse('{{data}}')
I couldn't pass data from my flask app to script section in html so I did this and it worked.
Upvotes: 0
Reputation: 496
Code example in response to @Lko comment to keep js in a separate file, see my comment to the previous post.
File structure: \main.py \static\script1.js \templates\result.html
HTML:
<!DOCTYPE html>
<html>
<head>
<title>New</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"></script>
</head>
<body>
<h1>Test</h1>
<div class="wrapper">
<canvas id="bar-chart" width="800" height="450"></canvas>
</div>
<!-- <script src="{{ url_for('static', filename='script1.js') }}"></script> -->
<script type = "text/javascript">
var labelsVar={{labels|tojson}};
var dataVar={{data|tojson}};
</script>
<script type = "text/javascript" src="{{ url_for('static', filename = 'script1.js') }}"></script>
</body>
</html>
Javascript:
console.log(labelsVar);
console.log(dataVar);
new Chart(document.getElementById("bar-chart"), {
type: 'bar',
data: {
labels: labelsVar,
datasets: [
{
label: "Population (millions)",
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
data: dataVar
}
]
},
options: {
legend: { display: false },
title: {
display: true,
text: 'Predicted world population (millions) in 2050'
}
}
});
Upvotes: 2
Reputation: 496
To render the javascript (replacing your variables) put the javascript in the html file to be rendered and use Flask jinja filter tojson: An example:
<!DOCTYPE html>
<html>
<head>
<title>New</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js"></script>
</head>
<body>
<h1>Test</h1>
<div class="wrapper">
<canvas id="bar-chart" width="800" height="450"></canvas>
</div>
<!-- <script src="{{ url_for('static', filename='script1.js') }}"></script> -->
<script>
//console.log({{labels|tojson}});
//console.log({{data|tojson}});
new Chart(document.getElementById("bar-chart"), {
type: 'bar',
data: {
labels: {{labels|tojson}},
datasets: [
{
label: "Population (millions)",
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
data: {{data|tojson}}
}
]
},
options: {
legend: { display: false },
title: {
display: true,
text: 'Predicted world population (millions) in 2050'
}
}
});
</script>
</body>
</html>
Upvotes: 1
Reputation: 71451
script1.js
is not being rendered by flask.render_template
as it is only being linked to by the script
tag. However, it is much better practice to send a request to the backend for jsonified data than attempt to render the values themselves in the template. Create an additional route in the Python file to return the values upon an ajax
request:
import json
@app.route("/")
def result():
return render_template("result.html")
@app.route('/get_data')
def get_data():
labels = ["Africa", "Asia", "Europe", "Latin America", "North America"]
data = [5578,5267,734,784,433]
return flask.jsonify({'payload':json.dumps({'data':data, 'labels':labels})})
Do not forget to include jquery
to support the ajax
call in the HTML:
<head>
<title>New</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.3.0/Chart.min.js">
</head>
Lastly, in script1.js
:
$(document).ready(function(){
var _data;
var _labels;
$.ajax({
url: "/get_data",
type: "get",
data: {vals: ''},
success: function(response) {
full_data = JSON.parse(response.payload);
_data = full_data['data'];
_labels = full_data['labels'];
},
});
new Chart(document.getElementById("bar-chart"), {
type: 'bar',
data: {
labels: _labels,
datasets: [
{
label: "Population (millions)",
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
data: _data
}
]
},
options: {
legend: { display: false },
title: {
display: true,
text: 'Predicted world population (millions) in 2050'
}
}
});
});
Upvotes: 7