[Twisted-web] [Nevow] nestedsequence renderer

Manlio Perillo manlio_perillo at libero.it
Sat Jul 29 13:39:51 CDT 2006


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><n:slot name="ctrl_label"/>
            <select n:render="nestedsequence">
              <n:attr name="name"><n:slot name="ctrl_name" /></n:attr>
              <option n:pattern="item" n:render="option">
                <n:attr name="value"><n:slot name="opt_value" /></n:attr>
                <n:slot name="opt_label" />
              </option>
            </select>
          </label>
        </li>
      </ul>
      <input type="submit" value="send" />
    </form>
  </body>
</html>



Any suggestions?



Thanks  Manlio Perillo



More information about the Twisted-web mailing list