Hi.
As suggested in a previous post, here is a (hopefully) reusable
nestedsequence renderer, for those who cannot use a hierarchical data
structure (like dictionary).
class IData(Interface):
# XXX choose a better name
pass
class ShinDataFactory(object):
# replacement for rend.DataFactory, to be used as a mixin
# XXX Is it possible to patch the default implementation? XXX
implements(inevow.IContainer)
def child(self, context, n):
args = []
if n.find(' ') != -1:
name, args = n.split(None, 1)
args = [arg.strip() for arg in args.split(',')]
else:
name = n
# we need to remember the last data directive name
context.remember(name, IData)
callable = getattr(self, 'data_%s' % name, None)
## If this page doesn't have an appropriate data_* method...
if callable is None:
## See if our self.original has an IContainer...
container = inevow.IContainer(self.original, None)
if container is None:
raise DataNotFoundError("The data named %r was not found
in %r." % (name, self))
else:
## And delegate to it if so.
return container.child(context, n)
if args:
return callable(*args)
return callable
def render_nestedsequence(self, context, data):
name = context.locate(IData)
nested_name = "nested_data_%s" % name
# XXX not sure, check for nested_nested_data
#context.remember(nested_name, IData)
callable = getattr(self, nested_name, None)
if callable is not None:
data = callable(context, data)
else:
# XXX Not sure
raise rend.DataNotFoundError("The nested data named %r was
not found in %r." % (name, self))
tag = context.tag
headers = tag.allPatterns("header")
pattern = tag.patternGenerator("item")
divider = tag.patternGenerator("divider",
default=tags.invisible)
content = [
(pattern(data=element), divider(data=element))
for element in data
]
if not content:
content = tag.allPatterns("empty")
else:
## No divider after the last thing.
content[-1] = content[-1][0]
footers = tag.allPatterns("footer")
return tag.clear()[ headers, content, footers ]
Here is an example:
class Main(ShinDataFactory, rend.Page):
addSlash = True
docFactory = loaders.xmlfile("nestedsequence.xhtml")
def data_control_list(self, ctx, data):
return [('a', "first"), ('b', "second")]
def nested_data_control_list(self, ctx, data):
print "nested_data_control_list", data
return [('1', "uno"), ('2', "due")]
def render_control(self, ctx, data):
ctx.fillSlots("ctrl_label", data[1])
ctx.fillSlots("ctrl_name", data[0])
return ctx.tag
def render_option(self, ctx, data):
ctx.fillSlots("opt_label", data[1])
ctx.fillSlots("opt_value", data[0])
return ctx
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:n="http://nevow.com/ns/nevow/0.1"
lang="it" xml:lang="it">
<head>
<title>Nested sequence</title>
</head>
<body>
<form action="post" method="post">
<ul n:render="sequence" n:data="control_list">
<li n:pattern="item" n:render="control">
<label>
participants (1)
-
Manlio Perillo