views:

1099

answers:

2

I'm working on a Django site that has multiple sections and subsections. I'd like to have several depths of template inheritance: a base template for the whole site, one base template for each section that inherits from the root base template, and so on. Here's a simplified version of my desired directory structure:

base.html
section1/
  base.html
section2/
  base.html
section3/
  base.html

What I would desire is for all the files under section1/ to contain something like {% extends "base.html" %}, meaning they would extend section1/base.html. section1/base.html would contain something like {% extends "../base.html" %}, meaning that it would extend the root-level base file. However, I couldn't find anything in the documentation suggesting this was possible, and I couldn't get Django to distinguish between "../base.html" and "base.html". ({% extends "../base.html" %} throws an error.) I suppose one workaround would be to rename all base files base_SECTIONNAME.html, and update all the files that inherit from them, but I am concerned that this might become difficult to maintain as my site becomes bigger and sections change names, etc. I would prefer a solution that takes advantage of the natural hierarchy specified by directories and subdirectories.

Any ideas?

+10  A: 

May be I oversee something, but all you want can be accomplished with the django template system. All extends calls are relative to template directories.

  1. In order for all base.html files in subdirectories to extend base.html, you just have to put a {% extends "base.html" %} into the files. section1/base.html would would look like that.

    {% extends "base.html" %}

    {# ... rest of your code ...#}

  2. Now, to get the files from section1 to extend section1/base.html you just have to put {% extends "section1/base.html" %} at the top of them. Same for section2, section3 and so on.

It is just that simple, but might not totally obvious in the documentation.

I hope, I understood your question.

Oliver Andrich
Right... relative paths won't work with extends.
Daniel
And they can't, cause you can have templates in various locations.
Oliver Andrich
+3  A: 

The accepted answer will work, but I do recommend using variable names to keep track of section structure. My personal preference would be a context processor. If, for example, your site's section organization is transparently reflected in the url, try something like:

# It may be convenient to make this function live in or near your url conf.
def convert_url_path_to_folder_path(path):
    # fill in the magic here

def sub_folder_available(request):
    folder = convert_url_path_to_folder_path(request.path)
    return {'subsection': folder, 'local_base':folder+'/base.html'}

Then in your template, just call

{% extends local_base %}

There are probably a dozen other ways to do this, but the main thing is to think about avoiding hard-coding the folder name into the template. This will get you a lot of mileage, especially since you can just drag and drop template between sections if they happen to be similar enough. Another thing you might add insert is:

def sub_folder_available(request):
    folder = convert_url_path_to_folder_path(request.path)
    # Check if local base exists:
    if os.access(folder+'/base.html',os.F_OK):
        base = folder+'/base.html'
    else:
        # revert to your global base
        base = 'base.html'
    return {'subsection': folder, 'base':base}

The nice advantage of this strategy is of course that you can get a fly-weight section up and running without any local base template at all.

David Berger
Nice post. I am not sure, if I loose more then I gain by this solution. I have to evaluate this.
Oliver Andrich
Obviously it's case by case. Just hinting what additional layers of organization can come into play.
David Berger