It’s difficult to find explanation on how we can render plotly chart on flask + jinja, so I’m sharing my code snippets.
First, in python, given a figure, turn that into json response of flask.
import plotly
from flask import Response, jsonify
import json # It's never "from flask import json"
def func(chart_name):
... generate necessary chart and save it to fig ...
return jsonify(json.dumps(fig, cls=plotly.utils.PlotlyJSONEncoder))
The chart data will be served via /get_chart/<chart_name>
@app.route("/get_chart/<string:chart_name>")
def get_chart(chart_name: str):
return <here, return the json from the func>
Prepare js code that can render the given json. Following code inserts a div to be filled with a chart. Chart data comes from /get_chart/<name>.
function fetchAndRenderChart(name) {
const parentTag = document.currentScript.parentElement;
const chartDiv = document.createElement("div");
chartDiv.alt = name;
const uniqueId =
"plotly-chart-" + Math.random().toString(36).substring(2, 9); # unique id for the div
chartDiv.id = uniqueId;
parentTag.appendChild(chartDiv);
fetch(`/get_chart/${name}`)
.then((response) => response.json())
.then((data) => {
let plotData = JSON.parse(data);
Plotly.newPlot(uniqueId, plotData.data, plotData.layout, {
responsive: true, # responsive to the browser width
});
});
}
Now in your html, load relevant scripts:
<head>
...
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<script src="....<path to fetchAndRenderChart of the above>..."></script>
</head>
Now, whenever you need a chart, render it as below. Note that js code looks for a parent to insert a child div. I’m using <p>…</p>. You will need one.
<p>
<script>fetchAndRenderChart("{{ CHART_KEYS.BITCOIN_PROCESSED }}");</script>
</p>
For better speed, I’m storing response of /get_chart/<chart_name> output in the redis using https://flask-caching.readthedocs.io/en/latest/ which is reloaded whenever I update dataset of my website.