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

This is my implementation of Rendering Arbitrary Objects with Nevow (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/286260) using CherryPy 2.1. CherryPy doesn't care about adapters or stuff like that, but since it is written in Python it is easy to add that sort of functionality.

Python, 86 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
84
85
86
import cherrypy

# here are our "arbitrary" object classes

class Person(object):
    def __init__(self, firstName, lastName, nickname):
        self.firstName = firstName
        self.lastName = lastName
        self.nickname = nickname

class Bookmark(object):
    def __init__(self, name, url):
        self.name = name
        self.url = url

# create a generic view

class GenericView(object):
    # subclasses should implement tmpl as string<--dict
    # substitution template
    tmpl = None
    
    def __init__(self, obj):
        self.obj = obj

    def render(self):
        return self.tmpl % self.obj.__dict__

# define our views

class PersonView(GenericView):
    "Define a person view"
    tmpl = """
    <div class="viewPerson">
        %(firstName)s %(lastName)s,
        <em>aka %(nickname)s</em>
    </div>"""

class BookmarkView(GenericView):
    "Define a bookmark view"
    tmpl = """
    <div class="bookmarkView">
        <a href="%(url)s">%(name)s</a>
    </div>"""

# here is our main application class

class ArbitraryObjects(object):
    header = "<html><head></head><body>"
    footer = "</body></html>"

    def __init__(self, handlers):
        self.handlers = handlers

    def map_view(self, obj):
        obj_class = obj.__class__
        return self.handlers[obj_class](obj)
    
    def index(self):
        yield self.header
        for item in objs:
            yield self.map_view(item).render()
        yield self.footer
    index.exposed = True

# now for some test data
objs = [
    Bookmark('TurboGears', 'http://www.turbogears.org'),
    Person('Robert', 'Brewer', 'fumanchu'),
    Person('Sylvain', 'Hellegouarch', 'Lawouach'),
    Bookmark('Subway', 'http://subway.python-hosting.com'),
    Bookmark('CherryPy', 'http://www.cherrypy.org'),
    Person('Remi', 'Delon', 'Remi'),
    ]


handlers = {
    Person:PersonView,
    Bookmark:BookmarkView
    }

# setup and start our application

cherrypy.root = ArbitraryObjects(handlers)

cherrypy.server.start()

Like the Nevow example, Person and Bookmark instances could have come from a database, pickled data or elsewhere. The views, subclasses of GenericView, simply render HTML strings for individual objects using string templates and the objects.__dict__ mapping. They are not required to use CherryPy, but they return nice HTML strings which CherryPy can in turn return to the requestor.

The ArbitraryObjects class is the main CherryPy class for this demonstration. It takes as an argument a dictionary of data classes mapped to data views, both of which are defined above. I call them handlers in this example. The map_view() method checks the class of an object and returns the correct view for it. The class exposes an index() method to the web which can be accessed at www.somehost.com:8080/ or www.somehost.com/index.

Even though I had to code the (albeit simple) view and "adaptation" code myself, this example is still shorter (and IMHO, easier to follow) than the Twisted/Nevow example in the Python Cookbook, 2nd Edition, thanks to the simplicity and expressiveness of CherryPy.

For more information on CherryPy, visit http://www.cherrypy.org