Fragments vs Raw¶
Problem. You want to emit multiple elements without a wrapper, or
splice in pre-rendered HTML — and you’re not sure whether to use
Fragment or Raw.
Solution. Use Fragment when the children are tagz objects.
Use Raw only when you have a trusted, already-rendered HTML string
that must pass through verbatim.
Fragment — wrapper-less group¶
from tagz import html, Fragment
# A function returns multiple top-level elements:
def render_header():
return Fragment(
html.h1("Title"),
html.h2("Subtitle"),
)
assert render_header().to_string() == "<h1>Title</h1><h2>Subtitle</h2>"
Fragments compose: pass one as a child of another tag and it renders its children inline.
from tagz import html, Fragment
page = html.body(
html.header("Top"),
Fragment(html.p("A"), html.p("B")),
html.footer("Bottom"),
)
assert page.to_string() == "<body><header>Top</header><p>A</p><p>B</p><footer>Bottom</footer></body>"
Raw — verbatim HTML¶
Raw takes a single string and emits it without escaping. Use
it for pre-rendered HTML you control, never for user input.
from tagz import html, Raw
# Trusted HTML fragment from elsewhere:
snippet = "<em>fast</em> & safe"
container = html.p("Status: ", Raw(snippet))
assert container.to_string() == "<p>Status: <em>fast</em> & safe</p>"
Which one do I want?¶
You have… |
Use |
|---|---|
Several |
|
A string you trust to be valid HTML |
|
A string that came from a user |
neither — pass it as a normal child so it gets escaped |
Output from another renderer (Markdown, Jinja) you trust |
|
XSS warning¶
Warning
Raw disables all escaping. If the string contains anything derived
from user input — directly or indirectly — you have an XSS vector.
Sanitise upstream with a library like
bleach before wrapping in
Raw.
See The escaping model for the full story.