[Twisted-web] nested nevow:data?
Donovan Preston
dp at divmod.org
Mon Aug 2 13:07:10 MDT 2004
On Aug 2, 2004, at 1:36 PM, Jeff Bowden wrote:
> Should it be possible to nest nevow:data declarations in a template?
> E.g.
>
> <html nevow:data="order" nevow:render="order">
> <head><title>Order <nevow:slot name="order_number"/></title></head>
> <body>
> <h1>Order <nevow:slot name="order_number"/></h1>
> <ul nevow:data="order_items" nevow:render="sequence">
> <li nevow:pattern="item" nevow:render="mapping">
> ... slots and stuff
> </li>
> </ul>
> </body>
>
>
> When I do this I get a big long stack trace rooted in
> nevow/accessors.py. It works fine if I remove the outer
> nevow:data="order" (and dummy up a static fillSlots call for
> "order_number" in render_order). It also works if I remove the inner
> section.
>
> I can work around the problem by putting the nevow:data="order"
> declaration in multiple places but it would be handy if I didn't have
> to. Is this a bug or is it by design?
What type is "order"? A data directive puts that data on the context
stack for the duration of that xml node; additional data directives are
handled by getting an IContainer adapter around the nearest data on the
stack. If, as I am suspecting, "order" is a rich python class, what you
want to do is either mix in DataFactory to your order class and declare
that it implements IContainer, or provide an IContainer adapter for
your order class (which is probably a subclass of DataFactory). For
example:
class OrderContainer(DataFactory):
def data_order_number(self, ctx, data):
return self.original.orderNumber
def data_order_items(self, ctx, data):
return self.original.items
compy.registerAdapter(OrderContainer, MyOrderClass, IContainer)
This is by design. It's intended to work in such a way that fragments
of template can have data pushed at them, and they can operate without
knowledge of the context of the entire page.
The biggest mistake people make in this area is when they do something
like push a list onto the context and then try to access another data_
method of the Page class. The directive will be satisfied by doing
IContainer(theList).child(theDirective), and since the IContainer
adapter for lists doesn't know how to handle anything except integer
indexes, they get an exception.
eg:
<ol n:data="someList" n:render="sequence">
<li n:pattern="header" n:data="someOtherDirective">
<!-- This won't work because "someList" is the topmost data on the
stack, and thus we will get an exception instead of having our
data_someOtherDirective method called on our Page -->
Header here
</li>
<li n:pattern="item" n:render="string">
Items here
</li>
</ol>
Woven used to have a syntax which used ".." and "/" to allow you to
navigate through the stuff on the data stack, but this hasn't yet been
implemented in nevow. It may be at some point in the future. For now,
the broken example above could be written like:
<ol>
<li n:data="someOtherDirective">
Header here
</li>
<n:invisible n:data="someList" n:render="sequence">
<li n:pattern="item" n:render="string">
Items here
</li>
</n:invisible>
</ol>
dp
More information about the Twisted-web
mailing list