![](https://secure.gravatar.com/avatar/6721e7c2fc10f17fcdda8c40f46797c6.jpg?s=120&d=mm&r=g)
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