[mod_python] Trouble with multiple class objects in publishermodel

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       *


More information about the Mod_python mailing list