Reputation: 49
I'm trying to create an HTML file, which certains Python variables that have to be evaluated. My code looks like this:
name = ['Nora', 'John', 'Jack', 'Jessica']
html = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Names</title>
</head>
<body>
<ul>
<li>Mother: <%= name[0] %></li>
<li>Father: <%= name[1] %></li>
<li>Son: <%= name[2] %></li>
<li>Daughter: <%= name[3] %></li>
</ul>
</body>
</html>
"""
Html_file = open("names.html","w")
Html_file.write(html)
Html_file.close()
However, the array is not interpreted during output. My HTML source looks like this:
...
<ul>
<li>Mother: <%= name[0] %></li>
<li>Father: <%= name[1] %></li>
<li>Son: <%= name[2] %></li>
<li>Daughter: <%= name[3] %></li>
</ul>
...
How can I evaluate the python code that's surrounded by <%= %>
?
Upvotes: 1
Views: 178
Reputation: 71461
You can use regex to more accurately evaluate the templating:
import re
name = ['Nora', 'John', 'Jack', 'Jessica']
def render_template(html, **kwargs):
return re.sub('\<%\=\s[a-zA-Z]+\[\d+\]\s%\>', '{}', html).format(*[kwargs.get(re.findall('[a-zA-Z]+', i)[0])[int(re.findall('\d+', i)[0])] for i in re.findall('(?<=\<%\=\s)[a-zA-Z]+\[\d+\](?=\s%)', html)])
print(render_template(html, name = name))
Output:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Names</title>
</head>
<body>
<ul>
<li>Mother: Nora</li>
<li>Father: John</li>
<li>Son: Jack</li>
<li>Daughter: Jessica</li>
</ul>
</body>
</html>
This solution will also work if name
elements are being accessed in random order:
html = """
<body>
<ul>
<li>Mother: <%= name[3] %></li>
<li>Father: <%= name[1] %></li>
<li>Son: <%= name[0] %></li>
<li>Daughter: <%= name[2] %></li>
</ul>
</body>
"""
print(render_template(html, name = name))
Output:
<body>
<ul>
<li>Mother: Jessica</li>
<li>Father: John</li>
<li>Son: Nora</li>
<li>Daughter: Jack</li>
</ul>
</body>
Upvotes: 0
Reputation: 33724
There're multiple ways of achieving this
First off, if you're on Python 3.6 or higher, there's a new syntax called f-string, which is basically a method of string formatting at run time.
name = ['Nora', 'John', 'Jack', 'Jessica']
html = f"""
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Names</title>
</head>
<body>
<ul>
<li>Mother: {name[0]}</li>
<li>Father: {name[1]}</li>
<li>Son: {name[2]}</li>
<li>Daughter: {name[3]}</li>
</ul>
</body>
</html>
"""
print(html)
The way you use f-string is fairly easy, add an f
in the beginning of the string, and use {
}
instead of <%= %>
.
If you're on any Python version, or wanted a version-compatible method, there are many other ways of string interpolation (ie. C-style string formatting %
, Python string formatting .format()
, and string concatenation), one of which (.format()
) is in the other answers.
re
and eval
If you don't have control over where you got the "need-to-be-substituted" html, or if you have to use the <%= %>
scheme, you can simply use a combination of re
and eval
:
from re import sub
name = ['Nora', 'John', 'Jack', 'Jessica']
html = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Names</title>
</head>
<body>
<ul>
<li>Mother: <%= name[0] %></li>
<li>Father: <%= name[1] %></li>
<li>Son: <%= name[2] %></li>
<li>Daughter: <%= name[3] %></li>
</ul>
</body>
</html>
"""
html = sub(r"<%=\s*(\S+)\s*%>", lambda l: eval(l.group(1)), html)
print(html)
Upvotes: 1
Reputation: 788
html = """<ul>
<li>Mother: {0} </li>
<li>Father: {1} </li>
<li>Son: {2} </li>
<li>Daughter: {3} </li>
</ul>"""
name = ['Nora', 'John', 'Jack', 'Jessica']
print(html.format(*name))
>>><ul>
<li>Mother: Nora </li>
<li>Father: John </li>
<li>Son: Jack </li>
<li>Daughter: Jessica </li>
</ul>
Upvotes: 0
Reputation: 9701
A string won't automatically evaluate code inside, but you can achieve this in a handful of ways:
Introduce placeholders and format your string:
name = ['Nora', 'John', 'Jack', 'Jessica']
html = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Names</title>
</head>
<body>
<ul>
<li>Mother: {0}</li>
<li>Father: {1}</li>
<li>Son: {2}</li>
<li>Daughter: {3}</li>
</ul>
</body>
</html>
"""
Html_file = open("names.html","w")
Html_file.write(html.format(name[0], name[1], name[2], name[3])
Html_file.close()
This is a very simple way to do it. There are more advanced approaches, such as using a template engine. Here you can read more about them.
Upvotes: 0