Embed Vizly Charts in Flask Templates
Flask apps render HTML through Jinja templates. Vizly provides Flask helpers that return chart HTML you can drop into a template, or ready-to-serve Flask responses.
Install the extra once:
pip install "vizly[flask]"
Chart HTML for a Jinja template
chart_html() returns a string you pass to your template. It defaults to a fragment, so you control where it sits in the page.
from flask import Flask, render_template
import vizly as vz
from vizly.integrations.flask import chart_html, assets_html
app = Flask(__name__)
@app.route("/")
def dashboard():
data = [
{"region": "Northeast", "sales": 86},
{"region": "Southeast", "sales": 64},
{"region": "Midwest", "sales": 71},
]
chart = vz.bar(data, x="region", y="sales", title="Sales by region")
return render_template(
"dashboard.html",
assets=assets_html(charts=[chart]),
chart_html=chart_html(chart, include_assets=False),
)
In the template, put the assets in the head and the chart fragment in the body:
<!DOCTYPE html>
<html>
<head>
{{ assets|safe }}
</head>
<body>
<h1>Sales dashboard</h1>
<div class="chart">{{ chart_html|safe }}</div>
</body>
</html>
Direct chart response
Skip the template and return chart HTML directly with chart_response(). This is useful for HTMX partial swaps and AJAX endpoints.
from vizly.integrations.flask import chart_response
@app.route("/chart/region/<region>")
def region_chart(region):
data = [{"product": "Widget", "sales": 42}]
chart = vz.bar(data, x="product", y="sales", title=f"{region} sales")
return chart_response(chart)
Multi-chart dashboard response
dashboard_response() renders several charts into one HTML document with a single ECharts load.
from vizly.integrations.flask import dashboard_response
@app.route("/dashboard")
def ops_dashboard():
cpu = [{"time": "00:00", "value": 34}, {"time": "01:00", "value": 38}]
mem = [{"time": "00:00", "value": 14}, {"time": "01:00", "value": 15}]
chart = vz.page(
charts=[
vz.line(cpu, x="time", y="value", title="CPU %"),
vz.area(mem, x="time", y="value", title="Memory GB"),
],
title="Ops dashboard",
)
return dashboard_response(chart.charts, title="Ops dashboard")
JSON for APIs
Return the chart option as a JSON response for clients that render ECharts themselves.
from vizly.integrations.flask import chart_json_response
@app.route("/api/chart")
def chart_api():
data = [{"date": "2026-01-01", "value": 42}]
chart = vz.line(data, x="date", y="value", title="Series")
return chart_json_response(chart)
Mixing into an existing layout
Load assets once and place several chart fragments anywhere in a complex template. ECharts loads once, and each fragment only adds its option JSON.
@app.route("/dashboard")
def dashboard():
charts = [
vz.bar([{"region": "Northeast", "sales": 86}], x="region", y="sales", title="Sales"),
vz.pie([{"name": "Enterprise", "value": 34}], names="name", values="value", title="Mix"),
]
return render_template(
"dashboard.html",
assets=assets_html(charts=charts),
charts_html="".join(chart_html(c, include_assets=False) for c in charts),
)
Tips
| Tip | Detail |
|---|---|
| Assets once | Put assets_html() in the template head and use include_assets=False on each fragment. |
| Mark safe | Flask escapes HTML by default. Use {{ value|safe }} for chart fragments and assets. |
| Fragments for swaps | Use chart_response() for HTMX partial swaps and other endpoints that return bare HTML. |
| JSON for SPAs | chart_json_response() gives API consumers the raw ECharts option. |