[Twisted-web] How to nest LiveElements? (getting a
MissingRenderMethod error)
kgi
iacovou at gmail.com
Fri Dec 1 07:35:34 CST 2006
Hi there.
I've got a web app that was originally written as a bunch of LiveElements at
the top level of a LivePage. I want to clean up this code and restructure it
such that several of the LiveElements are more modular; this entails making
some of the LiveElements contain other LiveElements.
Now, I could have *sworn* I've done this before, but whatever I try to do now
I get a nevow.errors.MissingRenderMethod exception.
At the end of this email is a cut-down example that exhibits the behaviour.
OuterWidget and InnerWidget are two LiveElement objects; they can both exist
happily in the LivePage, but if you uncomment the div containing an
innerWidget rendering directive (around line 28) you get:
File "/usr/lib/python2.4/site-packages/nevow/flat/ten.py", line 70,
in serialize
return partialflatten(context, obj)
File "/usr/lib/python2.4/site-packages/nevow/flat/ten.py", line 61,
in partialflatten
return flattener(obj, context)
File "/usr/lib/python2.4/site-packages/nevow/flat/flatstan.py", line
261, in DirectiveSerializer
renderer = rendererFactory.renderer(context, original.name)
File "/usr/lib/python2.4/site-packages/nevow/page.py", line 78, in
renderer
raise MissingRenderMethod(self, name)
nevow.errors.MissingRenderMethod: (<OuterWidget object at
0xb763482c>, 'innerWidget')
Can anyone shed any light on this?
There are also seemingly three styles for render methods that I've found. The
third was kind of guessed from the documentation of nevow.page.Element; I'm
not sure I've used it correctly, but I seem to recall reading that the
special "render_" prefixes will be going away and replaced by a renderer()
registration method, like the expose() method for athena callables.
Which is the preferred form?
def render_innerWidget ( self, ctx, data ):
elem = InnerWidget()
elem.setFragmentParent ( self )
return elem
def render_innerWidget ( self, ctx, data ):
elem = InnerWidget()
elem.setFragmentParent ( self )
return ctx.tag[f]
from nevow.page import renderer
def innerWidget ( self, request, tag ):
elem = InnerWidget()
elem.setFragmentParent ( self )
return elem
renderer(items)
Thanks,
Ricky
--
# Run using 'twistd -noy file.py'; point browser to localhost:8080
from nevow import athena
from nevow import stan
from nevow import loaders
from nevow import tags as T
from nevow import flat
from nevow import static
class InnerWidget ( athena.LiveElement ):
docFactory = loaders.stan (
T.div (
render = T.directive ( 'liveElement' ),
) [
T.p ( _class = 'bar' ) [ "This is InnerWidget text" ]
]
)
class OuterWidget ( athena.LiveElement ):
docFactory = loaders.stan (
T.div (
render = T.directive ( 'liveElement' ),
) [
T.p ( _class = "foo" ) [ "This is OuterWidget text" ],
# I can't create an InnerWidget inside the OuterWidget.
# T.div ( render = T.directive ( "innerWidget" ) ),
]
)
def render_innerWidget ( self, ctx, data ):
elem = InnerWidget()
elem.setFragmentParent ( self )
return ctx.tag[f]
class WebApp ( athena.LivePage ):
DOCTYPE_XHTML = (
'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" '
'"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'
)
_css = T.link (
rel = "stylesheet", type = "text/css", href = "css/style.css"
)
docFactory = loaders.stan (
[
T.xml ( DOCTYPE_XHTML ),
T.html [
T.head ( render = T.directive ( 'liveglue' ) ) [ _css ],
T.body [
T.div ( render = T.directive ( 'outerWidget') ),
# But I can create an InnerWidget at the top-level, inside
# athena.LivePage.
T.div ( render = T.directive ( 'innerWidget') ),
]
]
]
)
addSlash = True
def render_outerWidget ( self, ctx, data ):
f = OuterWidget()
f.setFragmentParent(self)
return ctx.tag[f]
def render_innerWidget ( self, ctx, data ):
f = InnerWidget()
f.setFragmentParent(self)
return ctx.tag[f]
def child_css ( self, ctx ):
return static.File ( 'css' )
def child_js ( self, ctx ):
return static.File ( 'js' )
from twisted.application import service, internet
from nevow import appserver
res = WebApp()
site = appserver.NevowSite ( res )
application = service.Application ( "WebApp" )
webService = internet.TCPServer ( 8080, site )
webService.setServiceParent ( application )
--
More information about the Twisted-web
mailing list