[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 

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.


<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 n:pattern="item" n:render="string">
		Items here

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:

	<li n:data="someOtherDirective">
		Header here
	<n:invisible n:data="someList" n:render="sequence">
		<li n:pattern="item" n:render="string">
			Items here


More information about the Twisted-web mailing list