Graham Dumpleton
grahamd at dscpl.com.au
Wed Nov 8 17:21:00 EST 2006
For starters, you are mixing up mod_python basic handlers and mod_python.publisher published functions. They are not the same thing. See my recent comment on mailing list about this: http://www.modpython.org/pipermail/mod_python/2006-November/022529.html BTW, which version of mod_python are you using? A few more things pointed out below. Martin Stoufer wrote .. > I am moving a set of python classes out of the Apache CGI model and into > mod_python. There is both inheritance and composition going on among > these classes. A few factory classes as well. It seems that when it > comes time to pull the generated content from the hierarchy of classes, > the string object returned to the initial class end up 'None'. > > I have stripped down my work as an example. If there is some larger > example of how this class structure should work, I would love to see it. > > from mod_python import apache > > class Dom: > def __call__(self, req): > from DomProdLibOutput import Html > self.form = req.form > self.output = Html('modPython') > self.host = self.form['host'].value > self.sortBy = self.form['sortby'].value > self.mode = self.form['mode'].value > if self.form.has_key('term'): > self.term=self.form['term'].value > else: > self.term = "" > req.content_type = "text/html" > req.send_http_header() Only need to call req.send_http_header() if using mod_python 2.7.X. > result = self.generate() > req.write(result) > return apache.OK You shouldn't be returning an Apache status code like this when using publisher. Status codes are for mod_python basic handlers, not publisher. Publisher needs to return the content, or if you have used req.write() it should return None (if mod_python 3.2 or later), or a string consisting of a singe space (prior to mod_python 3.2, to get around bug). Also, because publisher will automatically detect and set content type to 'text/html' when appropriate if returning the content, you don't need to set it yourself. Thus you can just have: return self.generate() and not worry about setting content, flush headers or explicitly writing back content. > def generate(self): > result = self.output.generate() > return result > > dom = Dom() Although you have specified a __call__() method so URL can just be '/.../dom', you are also exposing all the member data and member functions of your object as well and they can be access directly, which is really bad for this example. To hide member functions and data you don't want automatically accessible via a URL request, precede them with an underscore. Ie., use _generate() not generate() and store data like self._form and not self.form. > In the DomProdLibOutput file in the same dir: > > class Html: > def __init__(self, destination='screen'): > self.output = HtmlOutputFactory(destination).getOutput() > return > > def generate(self): > #result = "Foo in Html" > result = self.output.generate() > return result > > class HtmlModPython: > def __init__(self): > self.content = """Empty content in HtmlModPython""" > return > > def update(self, content): > self.content += content > return > > def generate(self): > return "Foo in HtmlModPython" > #return self.content > > class HtmlOutputFactory: > def __init__(self, destination): > self.dest = destination > return > > def getOutput(self): > if self.dest == 'screen': return HtmlScreen() > elif self.dest == 'modPython': return HtmlModPython() > elif self.dest == 'file': return HtmlFile() > else: > raise InvalidHtmlOutputDest, \ > "%s is not a supported output" % self.dest > return > > As an interesting side note, if I have the generate() in Html return > just the string, things work fine. Its when I try and resolve the string > stored by the HtmlModPython class instance that the resulting string > comes back 'None' irregardless of what the deepest generate() returns. Lost me there. I would very much suggest to track through what is happening that you use req.log_error() to log progress messages to the Apache error log file. > Do all these classes have to define __call__ as well? The __call__() method is only required for the Dom instance if you want URL to use the instance variable name only. Graham
|