Nevow Tutorial
Building a Page Hierarchy
URLs resemble a hierarchy; for example, in the URL http://example.com/foo/bar/baz.html, the HTML page baz.html can be considered to be a child of the path /foo/bar.
Note that Nevow gurus will point out that many other things other than HTML pages can exist at a particular URI and that the correct term is actually a "resource", but we will gloss over that fact for the time being.
As it happens, there are several methods for accessing page children. We will now examine these in turn; the details are available at http://starship.python.net/crew/mwh/nevowapi/nevow.rend.ChildLookupMixin.html#locateChild
The main ways of accessing children of a Page are:
- defining a method called childFactory() that returns a page object;
- defining a class attribute called children, a dict of names to page objects;
- defining a method called child_name() that returns a page object;
These approaches are implemented in the default implementation of locateChild(); this gives rise to a further method of accessing children:
- redefining locateChild()
However, it is usually possible to get the result you want using the default implementation and using one of the other methods.
Let's look at each of these examples in turn.
Using childFactory()
######################################################################
# Run using 'twistd -noy file.tac', then point your browser to
# http://localhost:8080
# A very simple Nevow site.
# Don't do it this way. Better ways are coming.
######################################################################
from twisted.application import service, internet
from nevow import appserver
from nevow import rend
from nevow import loaders
from nevow import tags as T
class SubPage ( rend.Page ):
docFactory = loaders.stan (
T.html [ T.head ( title = 'Sub Page' ),
T.body [ T.h1 [ "This is a Sub Page" ],
T.p [ "I lack much of interest." ]
]
]
)
class MainPage ( rend.Page ):
docFactory = loaders.stan (
T.html [ T.head ( title = 'Main Page' ),
T.body [ T.h1 [ "This is the Main Page" ],
T.p [ "However, try going ",
T.a ( href = 'sub' ) [ "here" ]
]
]
]
)
def childFactory ( self, ctx, name ):
return SubPage()
######################################################################
# Nevow Boilerplate
######################################################################
application = service.Application ( "nevowdemo" )
port = 8080
res = MainPage()
site = appserver.NevowSite ( res )
webService = internet.TCPServer ( port, site )
webService.setServiceParent ( application )
Note the following:
- We no longer use renderHTTP() to generate the page content;
- Instead, a class attribute docFactory defines the page content;
- A method childFactory() is used to access the children of a page;
- childFactory() receives the name of the path element being accessed; it can therefore return different pages based upon the name;
- The childFactory() is a catch-all: any child that is not found through another method causes childFactory() to be called;
- As a result of this, you can access SubPage through any path, not just sub;
- childFactory() may, however, choose not to return a page if it determines that one should not "exist" at that location.
Play around with this example until you're comfortable with it, then go on to DivmodNevow/TutorialFour
