1 Oct, 2024
This is a simple way of rendering HTML in Python.
But I think Python HTML Tags is even better.
import html
class Tag:
def __init__(self, name, attrs, children=None):
self.name = name
self.attrs = attrs
self.children = children
tag = Tag
class Placeholder:
def __init__(self, name):
self.name = name
def render_attrs(attrs):
all = []
for key, value in attrs.items():
if value is True:
all.append(' ' + html.escape(key))
elif value is False:
pass
else:
all.append(f' {html.escape(key)}="{html.escape(value)}"')
return ''.join(all)
def tag2template(t, indent='', parts=None, placeholders=None):
if parts is None:
parts = ['']
if placeholders is None:
placeholders = []
escaped_name = html.escape(t.name)
if t.attrs:
parts[-1] += indent+'<' + escaped_name + render_attrs(t.attrs) + '>'
else:
parts[-1] += indent+'<' + escaped_name + '>'
if t.children is not None:
if type(t.children) is list:
extra_indent = ' '
if t.name == 'html':
extra_indent = ''
for item in t.children:
if type(item) is Tag:
child_parts, child_placeholders = tag2template(item, indent=indent + extra_indent)
parts[-1] += '\n' + child_parts[0]
parts += child_parts[1:]
placeholders += child_placeholders
elif type(item) is str:
parts[-1] += indent+ extra_indent+ html.escape(item)
elif type(item) is Placeholder:
parts[-1] += '\n' + indent+ extra_indent
placeholders.append(html.escape(item.name))
parts.append('')
parts[-1] += '\n' + indent+'</' + escaped_name + '>'
elif type(t.children) is str:
parts[-1] += html.escape(t.children) + '</' + escaped_name + '>'
elif type(t.children) is Placeholder:
placeholders.append(html.escape(t.children.name))
parts.append('</' + escaped_name + '>')
return parts, placeholders
def tag2html(t):
parts, placeholders = tag2template(t)
assert placeholders == []
return parts[0]
def render_template(template, values=None):
if values is None:
values = {}
result = ''
parts, placeholders = template
result += parts[0]
for i, part in enumerate(parts[1:]):
result += values[placeholders[i]] + part
return result
if __name__ == '__main__':
import timeit
template = tag2template(tag('html', {'lang': 'en'}, [
tag('head', {}, [
tag('title', {}, Placeholder('title')),
tag('meta', {'name': "viewport", 'content': "width=device-width, initial-scale=1.0"}),
tag('meta', {'charset': "UTF-8"}),
]),
tag('body', {}, [
tag('h1', {}, Placeholder('title')),
Placeholder('body'),
])
]))
body = 'This is the body'
def run():
return render_template(template, dict(title='This is the title', body=body))
print(run())
number = 1000000
print(number / timeit.timeit(run, number=number))
Be the first to comment.
Copyright James Gardner 1996-2020 All Rights Reserved. Admin.