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