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.
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