It’s often much more practical to modify child nodes directly instead of giving each its own render_name method. Conveniently you can access child nodes of a node directly as attribute using the child node’s name:
from tdi import html
template = html.from_string("""
<html>
<body>
<ul class="menu" tdi="menu">
<li><a href="menu1" tdi="menu1">some menu item</a></li>
<li><a href="menu2" tdi="menu2">Editing Content & Attributes</a></li>
<li><a href="menu3" tdi="menu3">Other menu item</a></li>
</ul>
</body>
</html>
""")
class Model(object):
def __init__(self, page):
self._page = page
def render_menu(self, node):
if self._page == 1:
node.menu1.hiddenelement = True
elif self._page == 2:
node.menu2.hiddenelement = True
elif self._page == 3:
node.menu3.hiddenelement = True
model = Model(page=2)
template.render(model)
However, since the node object defines some names by itself, you cannot address every name by this method [1]. Thatswhy there’s a canonical (but more ugly), method too, which takes a string as the child node’s name. This method is also reasonable to use if you don’t know the node name in advance (same template as above, just a different model):
class Model(object):
def __init__(self, page):
self._page = page
def render_menu(self, node):
node("menu%d" % self._page).hiddenelement = True
The output is the same for both cases:
<html>
<body>
<ul class="menu">
<li><a href="menu1">some menu item</a></li>
<li>Editing Content & Attributes</li>
<li><a href="menu3">Other menu item</a></li>
</ul>
</body>
</html>
Directly accessed child nodes implicitely create another need – to not handle nodes twice (because a render_name method might be called for those nodes as well). You have three options here:
Don’t define render_name methods for those nodes. This may lead to strange effects if later such a method is created nevertheless (really strange if the creator just added a new node with the same name in a completely different context in ignorance of the old usage).
Returning a true value from a render method marks the current node and all of its children as done. No methods are called for this subtree anymore.
from tdi import html template = html.from_string(""" <html> <body> <ul class="menu" tdi="menu"> <li><a href="menu1" tdi="menu1">some menu item</a></li> <li><a href="menu2" tdi="menu2">Editing Content & Attributes</a></li> <li><a href="menu3" tdi="menu3">Other menu item</a></li> </ul> </body> </html> """) class Model(object): def __init__(self, page): self._page = page def render_menu(self, node): node("menu%d" % self._page).hiddenelement = True return True # avoid calling methods for subnodes def render_menu1(self, node): node.content = "shouldn't come here..." model = Model(page=2) template.render(model)
You can flag particular nodes for no automatic method calling in the template already with the * flag.
<html> <body> <ul class="menu" tdi="menu"> <li><a href="menu1" tdi="*menu1">some menu item</a></li> <li><a href="menu2" tdi="*menu2">Editing Content & Attributes</a></li> <li><a href="menu3" tdi="*menu3">Other menu item</a></li> </ul> </body> </html>
The result is the same, of course:
<html>
<body>
<ul class="menu">
<li><a href="menu1">some menu item</a></li>
<li>Editing Content & Attributes</li>
<li><a href="menu3">Other menu item</a></li>
</ul>
</body>
</html>
If you’re unsure about the structure of your template (especially after combining different templates or prerendering), you can ask TDI for it.
The → tree attribute of the template object holds the node tree. It can be visualized using the → to_string() method:
from tdi import html
template = html.from_string("""
<html>
<body>
<h1 tdi="doctitle">doc title goes here</h1>
<p tdi="intro">Intro goes <span tdi="where">here</span>.</p>
</body>
</html>
""")
print template.tree.to_string()
This script produces a simple nested node name output:
/
doctitle
intro
where
\
This output is useful for debugging purposes. It can also be used for simple automated tests if and how the node structure changed after modifications of a template, as well.
to_string() can also be more verbose:
print template.tree.to_string(verbose=True)
The verbose output gives more node information (if there is some, which is not the case here) and shortened versions of the text between the nodes. That way it’s easily possible to check if the template was parsed correctly (i.e. according to your expectations):
/
'\n<html>\n<body>\n '
doctitle
'doc title goes here'
'\n '
intro
'Intro goes '
where
'here'
'.'
'\n</body>\n</html>\n'
\
For your convenience the the to_string() method is connected to the string representations of the template object (nodes only) and the tree attribute (verbose variant), so you can just write:
print template
in order to get a quick abstract of the template.
[1] | The following attributes are owned by the node object: content, copy, ctx, hiddenelement, closedelement, iterate, raw, remove, render, repeat, replace. Python keywords cannot be used either. |
Enter search terms or a module, class or function name.