[mod_python] Source code displayed by Mozilla/Firefox

Graham Dumpleton grahamd at dscpl.com.au
Mon Jun 6 20:46:24 EDT 2005


Warning, long rambling response ...  :-)

Daniel J. Popowich wrote ..
> > BTW, why specifically are you using mpservlets as when using PSP you
> may
> > find they don't mesh very well? For example, one of the points of using
> > mpservlets is that by supplying its own write/writeln methods in the
> > servlet it does its own buffering of output. Because PSP is going to
> > write direct to the request object using req.write(), the buffering in
> > mpservlets is bypassed. Another reason people use mpservlets is that
> it
> > has some session support, but then so does PSP.
> 
> <soapbox>
> While output buffering and session handling are bonuses, the main
> reason I wrote mps was to have an OO view of the web.  Writing an
> abstract base class that manages the overall layout of a site and
> then writing subclasses for specific pages is, imho, very powerful.
> Also, being able to re-use base class features in every servlet
> (particularly form/query variable processing) saves hours of
> programming.
> </soapbox>

<bigger soapbox> :-) :-) :-)
I agree that an OO approach to writing response handlers is a good idea
and your HTMLPage servlet is great for people who want to hand craft the
HTML using code rather than using full blown templating systems, but the
original poster wasn't making use of that, nor the other inbuilt features
of the base class servlet. It may be that he just hasn't got to that point
yet, but for the code he was showing, it could equally be served by creating
a simple class which provides a "__call__()" method. Ie., the handler itself
is a callable object. 
</bigger soapbox>

To illustrate, I have included below some code which can be used in
combination with mod_python.publisher and which gives you the OO
type infrastructure. It is relatively straight forward and makes use of the
form processing and dispatch to handlers in seperate files features
that the mod_python.publisher package provides.

The only downside of using mod_python.publisher is that if you want
to mix static files in the same directory, you must use AddHandler and
a specific extension, usually ".py". Thus your Apache config for the code
given would look like:

  AddHandler python-program .py
  PythonHandler mod_python.publisher
  PythonDebug On 
    
  <Files *.psp>
  deny from all
  </Files>

I don't personally like having ".py" in a URL. One step better would be to
use:

  AddHandler python-program .psp
  PythonHandler mod_python.publisher
  PythonDebug On 
    
  <Files *.py>
  deny from all
  </Files>

This means you use a ".psp" extension, but mod_python.psp isn't used
as the actual handler. Instead, mod_python.publisher is used and you
would need a corresponding handler for each PSP file.

If all HTML files in the directory are going to be generated in this way,
ie., no static ".html" files, you could also use:

  AddHandler python-program .html
  PythonHandler mod_python.publisher
  PythonDebug On 
    
  <Files *.psp>
  deny from all
  </Files>
    
  <Files *.py>
  deny from all
  </Files>

Anyway, the idea of the code is that alongside each ".psp" file you have a
corresponding ".py" file which triggers the rendering of it. The servlet like
object would be named as "index" so that just the base name of the file
need be used in the URL with appropriate extension attached.

Thus, I might have a "example.psp" file containing:

  <html>
  <body>
  <p><%=message%></p>
  </body>
  </html>

Next to that I would have "example.py". With the very last config above, I
could access the rendered result as "example.html".

Anyway, here is the code. For starters it should be thrown into the "example.py",
but obviously the reusable classes should be separated out into a distinct
module so they can be access by more than one handler.

from mod_python import apache, util
psp = apache.import_module("mod_python.psp")

import os
import types


class Instance:

  def __init__(self,target,**args):
    self.__target = target
    self.__args = args

  def __call__(self,req):

    if not type(self.__target) in [types.ClassType,types.TypeType]:
      raise apache.SERVER_RETURN, apache.HTTP_INTERNAL_SERVER_ERROR

    instance = self.__target(req,**self.__args)

    if not callable(instance):
      raise apache.SERVER_RETURN, apache.HTTP_INTERNAL_SERVER_ERROR

    return util.apply_fs_data(instance,req.form)


class PSPServlet:

  content_type = "text/html"

  def __init__(self,req):
    self.req = req
    self.vars = {}

  def render(self):

    path = os.path.splitext(self.req.filename)[0] + ".psp"

    self.req.content_type = self.content_type
    self.req.send_http_header()

    template = psp.PSP(self.req,filename=path,vars=self.vars)
    template.run()

  def __call__(self):
    raise apache.SERVER_RETURN, apache.HTTP_INTERNAL_SERVER_ERROR


class MyServlet(PSPServlet):

  def __call__(self,message=""):
    if not message:
      message = "Give Blood!"

    self.vars["message"] = message

    self.render()


index = Instance(MyServlet)




More information about the Mod_python mailing list