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