There is a way, and it can look quite cool because you have unlimited option with html. Also if you are using plotly, the plots are already in html hence you can transfer them as they are and still keep the interactivity (zoom in, select etc)
First you create a template for Jinja. If the number of graphs is predefined then you just have a static one with placeholders (that's easier), otherwise you need to automate it. (using jinja )
Example of the template.html
<!DOCTYPE html>
<html style="text-align:center;">
<head>
<title> My Report </title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<style>
....
<div class="main box_around">
<h2 id="%count_of_unique_obs_over_time"><span> Count of unique obs Over Time </span>
<hr style="width:60%;">
</h2>
<p style="font-size: 21px;">
<div style="overflow-y:scroll;height: 500px; " align="center"> {{count_of_missing_values_over_time_fig }}</div>
</p>
</div>
...
Then you input the graph. ( I use plotly that you can use the ".to_html()" method)
data = {
"table_name_clean":table_name_clean,
...
"count_of_unique_obs_over_time_fig": count_of_unique_obs_over_time_fig.to_html()
}
and finally you fill the template with the data and you save.
with open('html_template.html', 'r') as f:
html_string = f.read()
j2_template = Template(html_string )
with open(save_output_path, 'w') as f:
f.write(j2_template.render(data))