Welcome, guest | Sign In | My Account | Store | Cart

Here you can find a very basic example of how nevow (twisted's new web toolkit) works. As you see the purpose of this example is to represent in a <ul> a list of dictionaries. I can translate a dict into some tags thanks to the built-in mapping render.

Python, 83 lines
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
from twisted.application import service, internet

from nevow import rend, loaders, appserver

class Pg(rend.Page):
    docFactory = loaders.htmlstr("""
    <html><head><title>Nested Maps Sequence Rendering</title></head>
        <body>
            <ul nevow:data="dct" nevow:render="sequence">
                <li nevow:pattern="item" nevow:render="mapping">
                    <span><nevow:slot name="name">Name</nevow:slot></span>
                    <span><nevow:slot name="surname">Surname</nevow:slot></span>
                    <span><nevow:slot name="age">Age</nevow:slot></span>
                </li>
            </ul>
        </body>
    </html>
    """)
    def __init__(self, dct):
        self.data_dct = dct
        rend.Page.__init__(self)

dct = [{'name':'Mark',
            'surname':'White',
            'age':'45'},
          {'name':'Valentino',
            'surname':'Volonghi',
            'age':'21'},
           {'name':'Peter',
             'surname':'Parker',
             'age':'Unknown'}
        ]

site = appserver.NevowSite(
    Pg(dct)
)
 
application = service.Application("example")
internet.TCPServer(8080, site).setServiceParent(application)

####
#### Using stan
####

from nevow import tags as T
from nevow import rend, loaders, appserver
from twisted.application import service, internet

class Pg(rend.Page):
    docFactory = loaders.stan(
        T.html[T.head[T.title["Nested Maps Sequence Rendering"]],
            T.body[
                T.ul(data=T.directive("dct"), render=T.directive("sequence"))[
                    T.li(pattern="item", render=T.directive("mapping"))[
                        T.span[T.slot("name")],
                        T.span[T.slot("surname")],
                        T.span[T.slot("age")],
                    ]
                ]
            ]
        ]
    )
    def __init__(self, dct):
        self.data_dct = dct
        rend.Page.__init__(self)

dct = [{'name':'Mark',
        'surname':'White',
        'age':'45'},
       {'name':'Valentino',
        'surname':'Volonghi',
        'age':'21'},
       {'name':'Peter',
        'surname':'Parker',
        'age':'Unknown'}
      ]

site = appserver.NevowSite(
    Pg(dct)
)
 
application = service.Application("example")
internet.TCPServer(8080, site).setServiceParent(application)

Before starting the discussion I need to tell you the dependencies :). First of all this little recipe uses Twisted.web as its web server so it is run by typing twistd -noy filename.py a .tac extension would be better but not mandatory.

There are 2 dependencies: nevow 0.2 (at least) and twisted 1.3 (at least). You can find both packages in these 2 urls: http://www.divmod.org (nevow) http://www.twistedmatrix.com (twisted)

There are at least 3 things that deserve to be noted: 1) Since nevow is DOM Tree based, it uses its own namespace to mark special nodes (tags) of the template, and bind them to the class' methods. There are 2 kinds of directives: data directives and render directives. Directives are the markers that will call your methods while the others are markers that need to be processed by the methods that you bound to the outer directives.

2) The default mapping renderer method maps slot names to keys inside the dict and fills the slots (marked with ) with the value of the corresponding key

3) Nevow makes use of the loaders module in order to process the template. There are many different loaders depending on which technology you are going to use to write the template. Nevow has it's own module to describe an (x)html page using python code, which is called stan, an s-expr like syntax. Also you can load html strings containing a template or xml strings (like I'm doing right now) or html/xml files. In the last few lines you can see an example of how to write an equivalent template using stan.

5 comments

B T 17 years, 10 months ago  # | flag

delete. I don't believe this belongs here. Try including this example with the nevow download.

Duncan McGreggor 17 years, 10 months ago  # | flag

I disagree... I have not read the ASPN standards, so maybe I'm way out of line here, but:

1) This is python

2) Twisted is python (and excellent python at that)

3) Nevow is cool python.

I could see where some might want to keep recipes here "pure" python... but what's pure? Stuff that was left field years ago is part of tomorrow's python release; twisted and nevow's not that far off the mark, don't you think?

Juan Stang 17 years, 10 months ago  # | flag

Ah, don't get yourself in a twist ... I don't mind this being here. I see your point, that this cookbook shouldn't become a soapbox for pet projects. But I think this is valid. I've been about to read the Nevow introduction three times now and I've gotten sidetracked each time. This gave me a really good overview very quickly. And developers looking for a Web framework shouldn't have to go running all over Google just to get some basic info.

Still, don't forget Webware at http://www.webwareforpython.org. It's mature, as powerful as anything, and, for Java developers, a familiar paradigm built on servlets and templating. It's a good counterbalance to Nevow since, in many ways, they're very different.

Robin Bryce 17 years, 3 months ago  # | flag

re: what does this do ? I think the missing link is something like:

httpd = internet.TCPServer(8080, site)
httpd.setServiceParent(application)
httpd.startService()

or just

from twisted.internet import reactor
backlog=5
reactor.listenTCP(8080, site, backlog, '127.0.0.1')
reactor.run()
Bartosz Ptaszynski 17 years ago  # | flag

httpd = internet.TCPServer(8080, site) httpd.setServiceParent(application) httpd.startService()

Doesn't seem to work for me, reactor does. Anybody know why it just exits? (no error, or anything)