[mod_python] Building a web application using Cheetah and mod_python

Dirk van Oosterbosch, IR labs labs at ixopusada.com
Sat Oct 28 13:12:08 EDT 2006


Hi,

I am also working on a "cms"-like website system, using mod_python  
and Cheetah, though I've not yet tied these both up together, to be  
fully functional. Still working on the smaller subparts of the system.
So I follow this subject with great interest.

It feels like the core of this discussion is about making sure the  
cheetah modules gets reloaded when they change. I didn't conduct any  
tests yet, still trying to grasp the exact mechanisms underneath.

>> [...]
>> Is this the best way to import template modules and then evaluate  
>> them?
>
> No, in as much as you are having to create a parallel hierarchy of  
> publisher
> handlers for each Cheetah page. You would be better off using a custom
> handler which does the dispatch direct to the compiled Cheetah  
> template
> classes.

I'm not sure if this helps, but I've got a similar setup. There is  
one handler in a main.py that handles all requests. This main  
connects to a database, to find out which Cheetah template to use,  
and loads and fills this template. Also I've got a directory which  
hold all the python files directly necessary for the system (/var/www/ 
python) and an other directory to hold my templates. (/var/www/python/ 
templates)

If inside this main.py I would use an `apache.import_module 
(fooTemplate)` instead of just `from fooTemplate import fooTemplate`,  
that would mean that the fooTemplate is reloaded if it changed,  
doesn't it?
But would it also mean that all the other templates which are  
imported through their inheritance would be reloaded if they are  
changed?

Most of my templates are inheriting parent-templates using the  
Cheetah standard
#from bar import bar
#extends bar

It's easy to create a whole directory with fresh modules, using the  
shell `cheetah compile *.tmpl`. But is there also a way to ensure me  
that apache is reloading them, if I do that? (i.e. an other way than  
restarting apache, which I have to do frequently while debugging this  
system :-(


And sometimes I am not importing a compiled template in main, but  
create a new template from a text/tmpl file
`t = Template(file = "foobar.tmpl", searchList = [dict, obj])`
What does creating a template on the fly like this, mean for  
reloading a changed inherited template?


>> This second file only works if I add /var/www/app/templates to my
>> PythonPath.  And, due to (2) above, I then also have to add
>> /var/www/app to PythonPath.  Is this really necessary?=
>
> With the version of mod_python you are using, yes it is necessary.

I am also adding the templates directory to my PythonPath, but since  
I am not yet running my code from Apache, I haven't yet discovered  
problems with loading the rest of my python modules from my /var/www/ 
python. But if I hit those issues, I'll now know how to fix them, ;-)


BTW, (OT)

>>    templateModule = apache.import_module("templates/myTemplate")
>
> Using '/' in the module name like this is not portable and is  
> dependent
> on peculiarities of the behaviour of Python on a specific platform.  
> It will
> not for example work on Mac OS X and also possibly not on Windows.

I am working on a mac and also using slashes `/` to delimit my paths,  
so no problems there. (Didn't try from mod_python though & dunno what  
will happen on Windows). However I know of portability issues, so I  
am only using paths/with/slashes in my configuration files, if I need  
to create a path in code I'm using os.path.join()




> Things are a bit easier to manage and easier to predict when  
> mod_python 3.3
> can be used. Version 3.3 of mod_python hasn't been released yet,  
> but is quite
> close.

I am eagerly awaiting :-)
best

dirk



-----------------------------
Dirk van Oosterbosch
de Wittenstraat 225
1052 AT Amsterdam
the Netherlands

http://labs.ixopusada.com
-----------------------------


On 28-okt-2006, at 5:32, Graham Dumpleton wrote:

>
> On 28/10/2006, at 7:44 AM, Sebastian Celis wrote:
>
>> Hello,
>>
>> I am new to this list and have just recently begun to work on a
>> project where I wish to use mod_python.publisher and cheetah to drive
>> an entire web application.  I apologize if the following topics have
>> been discussed to death recently, but I have read through the
>> documentation on both sites and have searched through the mailing- 
>> list
>> archives and while I have seen similar discussions, I have yet to  
>> find
>> definitive answers.  I am able to get most things to work, however I
>> can't help but feel that there are better ways of approaching some of
>> my situations.
>>
>> First, I'll quickly describe my directory structure:
>>
>> /var/www/app -- The base directory to the web application.  This will
>> directly contain most of the python files that correspond directly to
>> URLs.  For example, index.py, login.py, etc.  In this directory.
>> /var/www/app/templates -- Contains all of my cheetah templates.
>> /var/www/app/include -- Contains the python utility modules I am
>> writing specifically for this application.
>>
>> Now, onto the questions.
>>
>>
>> 1) Importing compiled cheetah templates
>>
>> Assume I have code like the following in /var/www/app/test1.py
>>
>> ######################################
>> from mod_python import apache
>> from Cheetah.Template import Template
>>
>> def index(req):
>>    req.content_type = "text/html"
>>
>>    dict = {'title': 'My Title!', 'message': 'Hello world!'}
>>    templateModule = apache.import_module("templates/myTemplate")
>
> Using '/' in the module name like this is not portable and is  
> dependent
> on peculiarities of the behaviour of Python on a specific platform.  
> It will
> not for example work on Mac OS X and also possibly not on Windows.
>
>>    t = getattr(templateModule, "myTemplate")()
>>    searchList = t.searchList()
>>    searchList.insert(0, dict)
>>
>>    return(t.respond())
>> ######################################
>>
>> Is this the best way to import template modules and then evaluate  
>> them?
>
> No, in as much as you are having to create a parallel hierarchy of  
> publisher
> handlers for each Cheetah page. You would be better off using a custom
> handler which does the dispatch direct to the compiled Cheetah  
> template
> classes. See the mod_python handler described in:
>
>   http://wiki.cheetahtemplate.org/cheetah-recipes.html
>
>> 2) Modifying PythonPath prevents modules from being imported
>>
>> Inside file /var/www/app/test2.py, I have the following code:
>>
>> import config
>> (or)
>> config = apache.import_module("config")
>>
>> Both of these commands load /var/www/app/config.py, and seem to work
>> fine.  However, if I add
>>
>> PythonPath "['/var/www/app/templates']+sys.path"
>>
>> to my apache configuration, I get an error next time I run test2.py.
>>
>> ###
>> Mod_python error: "PythonHandler mod_python.publisher"
>>
>> Traceback (most recent call last):
>>
>>  File "/usr/lib/python2.4/site-packages/mod_python/apache.py", line
>> 299, in HandlerDispatch
>>    result = object(req)
>>
>>  File "/usr/lib/python2.4/site-packages/mod_python/publisher.py",
>> line 213, in handler
>>    published = publish_object(req, object)
>>
>>  File "/usr/lib/python2.4/site-packages/mod_python/publisher.py",
>> line 412, in publish_object
>>    return publish_object(req,util.apply_fs_data(object, req.form,  
>> req=req))
>>
>>  File "/usr/lib/python2.4/site-packages/mod_python/util.py", line
>> 439, in apply_fs_data
>>    return object(**args)
>>
>>  File "/var/www/app/test2.py", line 8, in index
>>    config = apache.import_module("config")
>>
>>  File "/usr/lib/python2.4/site-packages/mod_python/apache.py", line
>> 461, in import_module
>>    f, p, d = imp.find_module(parts[i], path)
>>
>> ImportError: No module named config
>> ###
>>
>> Why does this initially work but then stop working once I add a
>> directory to my path?  I can fix it by adding '/var/www/app' to my
>> PythonPath as well, but I don't understand why it didn't work before
>> that.
>
> That is just how mod_python has always worked. Setting PythonPath
> stops mod_python looking in the directory the handler was specified
> for. Yes it is a pain. FWIW, this behaviour changes in mod_python 3.3
> where the whole issue of module importing is dealt with a bit  
> differently
> and is much more consistent and predictable.
>
> Current versions of mod_python have a lot of issues when it comes
> to the module importer. You should really have a read of:
>
>   http://www.dscpl.com.au/wiki/ModPython/Articles/ 
> ModuleImportingIsBroken
>
>> 3) Cheetah and #include
>>
>> I have read a lot about why mod_python sets the current working
>> directory to '/', but this seems to be causing some larger problems
>> when cheetah comes into play.  (3) and (4) discuss two issues that I
>> am having trouble with.
>>
>> Here is /var/www/app/templates/testPage.tmpl:
>> ###
>> #include 'header_include.tmpl'
>> <head>
>> <title>$title</title>
>> </head>
>> <body>
>> <p>$message</p>
>> </body>
>> #include 'footer_include.tmpl'
>> ###
>>
>> However, as this actually tries to load /header_include.tmpl and
>> /footer_include.tmpl instead of the ones located in my templates
>> directory, this will not work.
>
> If you are going to use compiled templates, you are possibly better  
> off using
> a site page base class and have specific pages extend that page. These
> common blocks are then accessible through the base class. This  
> means you
> get the benefit of compiled code for the included blocks as well,  
> instead of
> it having to be interpreted each time.
>
>> I came up with two workarounds,
>> however I don't really love either:
>>
>> a)
>>
>> ###
>> #include os.path.join(os.path.dirname(__file__),  
>> 'header_include.tmpl')
>> <head>
>> <title>$title</title>
>> </head>
>> <body>
>> <p>$message</p>
>> </body>
>> #include os.path.join(os.path.dirname(__file__),  
>> 'footer_include.tmpl')
>> ###
>>
>> b)
>>
>> Actually pass $templatesDir into all of my templates and then  
>> instead call:
>>
>> ###
>> #include os.path.join(templatesDir, 'header_include.tmpl')
>> <head>
>> <title>$title</title>
>> </head>
>> <body>
>> <p>$message</p>
>> </body>
>> #include os.path.join(templatesDir, 'footer_include.tmpl')
>> ###
>>
>> I guess I'm leaning toward (a), but both seem cumbersome and slower
>> than necessary.  Is there a better way to do this?
>
> If my memory of Cheetah is correct, then extending from a site page  
> which
> has reusable bits like this as I describe above is better.
>
>> 4) Cheetah and inheritance
>>
>> Assume these two files:
>>
>> /var/www/app/templates/overall_base.tmpl
>> ###
>> <?xml version="1.0" encoding="UTF-8"?>
>> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
>>          "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
>> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
>> <head>
>>    <title>$title</title>
>> </head>
>> <body>
>>    $bodyContent
>> </body>
>> </html>
>> ###
>>
>> /var/www/app/templates/overall_base_extender.tmpl
>> ###
>> #overall_base = apache.import_module("overall_base")
>> (or)
>> #from overall_base import overall_base
>>
>> #extends overall_base
>> #def title
>> Welcome to Foo
>> #end def
>> #def bodyContent
>> Hello world!
>> #end def
>>
>> This second file only works if I add /var/www/app/templates to my
>> PythonPath.  And, due to (2) above, I then also have to add
>> /var/www/app to PythonPath.  Is this really necessary?=
>
> With the version of mod_python you are using, yes it is necessary.
>
>> #overall_base = apache.import_module("overall_base",
>> path=[os.path.dirname(__file__)])
>>
>> doesn't seem to work inside the cheetah template file.  Even
>>
>> #sys.path.append(os.path.dirname(__file__))
>> #overall_base = apache.import_module("overall_base")
>
> That one I am not sure about. You may be hitting one of the other  
> problems
> with PythonPath based module importing which is you can't easily  
> have the
> same name module in different directories and be sure you import  
> the one
> you want.
>
> In general I wouldn't recommend using apache.import_module() within
> Cheetah templates explicitly.
>
>> doesn't seem to work.  Is there any way to get inheriting  
>> templates to
>> work without modifying PythonPath to include all the directories  
>> where
>> my base templates might be located?
>
> Not really.
>
>> I apologize for the huge length of this e-mail.  I am still fairly  
>> new
>> to mod_python and cheetah, but so far I really like what I see.  I
>> just feel like there are a few issues I need to wrap my head around
>> before I can really dive into developing applications.  Any pointers
>> or help with these issues that you can provide would be greatly
>> appreciated.
>
> Things are a bit easier to manage and easier to predict when  
> mod_python 3.3
> can be used. Version 3.3 of mod_python hasn't been released yet,  
> but is quite
> close. If you want to try the source for mod_python out of the  
> Subversion
> repository, then can suggest better ways of doing things.
>
> Graham
> _______________________________________________
> Mod_python mailing list
> Mod_python at modpython.org
> http://mailman.modpython.org/mailman/listinfo/mod_python
>







More information about the Mod_python mailing list