views:

561

answers:

2

So I've done the trivial "warmup" apps with GAE. Now I'd like to build something with a more complex directory structure. Something along the lines of:

siteroot/
 models/
 controllers/
  controller1/
  controller2/
  ...
 templates/
  template1/
  template2/
  ...

..etc. The controllers will be Python modules handling requests. They would then need to locate (Django-style) templates in associated folders. Most of the demo apps I've seen resolve template paths like this:

path = os.path.join(os.path.dirname(__file__), 'myPage.html')

...the __ file __ property resolves to the currently executing script. So, in my above example, if a Python script were running in controllers/controller1/, then the 'myPage.html' would resolve to that same directory -- controllers/controller1/myPage.html -- and I would rather cleanly separate my Python code and templates.

The solution I've hacked together feels... hacky:

base_paths = os.path.split(os.path.dirname(__file__))
template_dir = os.path.join(base_paths[0], "templates")

So, I'm just snipping off the last element of the path for the currently running script and appending the template directory to the new path. The other (non-GAE specific) solutions I've seen for resolving Python paths seem pretty heavyweight (such as splitting paths into lists and manipulating accordingly). Django seems to have an answer for this, but I'd rather stick to the GAE API, vs. creating a full Django app and modifying it for GAE.

I'm assuming anything hard-coded would be non-starter, since the apps live on Google's infinite server farm. So what's a better way?

A: 

The dirname function returns an absolute path, use relative paths. See what is the current directory when your controllers are executed with os.path.abspath(os.path.curdir) and build a path to the templates relative to that location (without the os.path.abspath part of course).

This will only work if the current directory is somewhere inside siteroot, else you could do something like this:

template_dir = os.path.join(os.path.dirname(__file__), os.path.pardir, "templates")
Toni Ruža
+2  A: 

You can't use relative paths, as Toni suggests, because you have no guarantee that the path from your working directory to your app's directory will remain the same.

The correct solution is to either use os.path.split, as you are, or to use something like:

path = os.path.join(os.path.dirname(__file__), '..', 'templates', 'myPage.html')

My usual approach is to generate a path to the template directory using the above method, and store it as a member of my controller object, and provide a "getTemplatePath" method that takes the provided filename and joins it with the basename.

Nick Johnson