Sharing templates and public files between Pylons projects

From Jonathan Gardner's Tech Wiki
Jump to: navigation, search

Purpose

If you like to share templates and static files among your projects, here's a neat way to do so that is pretty straightforward.

Setting up the Template Package

First, setup a template package. A good example is the twitter_bootstrap module I've created. Basically, it provides a module that provides two functions, one that calculates the path to the static files and one that calculates the path to the templates.

Add the Dependency

In the project you'd like to import the files into, add the package as a dependency.

Modify config/environment.py

We're going to modify config/environment.py to add the static files and templates in the respective search paths.

Find the section of code that looks something like this:


# Pylons paths
root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
paths = dict(root=root,
             controllers=os.path.join(root, 'controllers'),
             static_files=os.path.join(root, 'public'),
             templates=[os.path.join(root, 'templates')])

Change it so that it looks like this:

# import the module providing the files and templates
import twitter_bootstrap

...
# Pylons paths
root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
paths = dict(root=root,
             controllers=os.path.join(root, 'controllers'),
             static_files=[
                os.path.join(root, 'public'),
                twitter_bootstrap.public_path()],
             templates=[
                os.path.join(root, 'templates'),
                twitter_bootstrap.template_path()])

You'll note that while the templates was originally a list, the static_files were not! If you try to run your site with this code, it will not work at all.

Modify config/middleware.py

Near the bottom of config/middleware.py, there is a section that looks like this:

if asbool(static_files):
    # Serve static files
    static_app = StaticURLParser(config['pylons.paths']['static_files'])
    app = Cascade([static_app, app])

We need to change it to allow multiple static_files.

if asbool(static_files):
    # Serve static files
    static_app = [
        StaticURLParser(path)
        for path in config['pylons.paths']['static_files']]
    app = Cascade(static_app+[app])

Using It

Since we put the imported files and templates later in the chain, if there is a similarly named file or template in your project, you will override that. So you need to know what it is you imported and be careful not to overwrite things unless you mean to.

If you want to use a static file, just refer to it the same way you would to your own static file. For instance, if there was a file bootstrap/bootstrap.js under the static files you imported, then url('/bootstrap/bootstrap.js') should pick it up.

For templates, it works the same way.

Here's an example base.mako that I use for my projects:

<%inherit file="/bootstrap/basic.mako"/>
 <%!
     from webhelpers.html.tags import link_to
 %>
 <%def name="title()">\
 % if hasattr(c, 'title'):
 ${c.title}
 % else:
 Slimgur
 % endif
 </%def>\
 <%def name="brand()">Slimgur</%def>\
 <%def name="footer()">\
 <div class="container-fluid">
   <div class="row-fluid">
     <div class="span12">
       <hr/>
     </div>          
   </div>
   <div class="row-fluid">
     <div class="span6" style="text-align: left;">
     Copyright © 2012 ${link_to(
       'Jonathan Gardner',
       'mailto:jgardner@jonathangardner.net')}. ALL RIGHTS RESERVED
     </div> 
     <div class="span6" style="text-align: right;">
       ${link_to('Email me', 'mailto:jgardner@jonathangardner.net')} for feedback or ideas!
     </div>  
   </div>
 </div>
 </%def>\
 ${next.body()}

The template /bootstrap/basic.mako is located within the twitter_bootstrap module's templates.