Graham Dumpleton
grahamd at dscpl.com.au
Wed Nov 8 17:49:55 EST 2006
Martin Stoufer wrote .. > > This is a bit to digest, thanks for being so thorough. In comment to your > mentioned article, I could not rectify if the named args (host, sortBy, > etc..) would be always required when passed to the __call__ function. Or is > that just when you are dealing with a standalone method in your example? The short of it, is that using publisher instead of: > 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 = "" you could have written: class Dom: def __call__(self, req, host, sortBy, mode, term=''): from DomProdLibOutput import Html self.host = host self.sortBy = sortyBy self.mode = mode self.term = term If a form field is optional, give it a default value in the prototype. This might be space if appropriate, or even None if you truly want to know if the field was supplied. Graham > 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: > > [1]http://www.modpython.org/pipermail/mod_python/2006-November/022529.html > > BTW, which version of mod_python are you using? > > > Apache 2.2.3/mod_python 3.2.10/Python 2.5 > > 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 > > > -- > * Martin C. Stoufer * > * DIDC/DSD/ITG * > * Lawrence Berkeley National Lab * > * MS 50B-2215 510-486-8662 *
|