You should consider using dominate. You can build html elements and combine raw html. As a proof of concept:
from dominate.tags import *
from dominate.util import raw
head_title = 'test' # Replace this with whatever content you like
raw_html_content = '<table border="1" class="dataframe"></table>' # Replace this with df.to_html()
print(html(head(title(head_title)), body(raw(raw_html_content))))
This will output:
<html>
<head>
<title>test</title>
</head>
<body><table border="1" class="dataframe"></table> </body>
</html>
Alternatively you can build the html with BeauitfulSoup. It a lot more powerful, but then you have to write a lot more code.
from bs4 import BeautifulSoup
raw_html_content = '<table border="1" class="dataframe"></table> '
some_content = 'TODO <a href="#">click here</a>'
soup = BeautifulSoup(raw_html_content, features='html.parser') # This would contain the table
paragraph = soup.new_tag('p') # To add content wrapped in p tag under table
paragraph.append(BeautifulSoup(some_content, features='html.parser'))
soup.append(paragraph)
print(soup.prettify())
This will output:
<table border="1" class="dataframe">
</table>
<p>
TODO
<a href="#">
click here
</a>
</p>
You can use python built in f-string to add replacement fields with variables. Simply add the character f at the start of the string and then pass in the variable wrapped in brace brackets. This makes the html easier to read and edit. The downside is that to display brace brackets within the content, you have to use double brace brackets (see thead below).
An example e.g:
main_content = '<table border="1" class="dataframe"></table>' # // df.to_html()
msg = "custom messages"
html = f"""
<html>
<head>
<style>
thead {{color: green;}}
tbody {{color: black;}}
tfoot {{color: red;}}
table, th, td {{
border: 1px solid black;
}}
</style>
</head>
<body>
<h4>{msg}</h4>
{main_content}
</body>
</html>
"""
print(html)
This will output:
<html>
<head>
<style>
thead {color: green;}
tbody {color: black;}
tfoot {color: red;}
table, th, td {
border: 1px solid black;
}
</style>
</head>
<body>
<h4>custom mesagges</h4>
<table border="1" class="dataframe"></table>
</body>
</html>