In a recently started Pylons project, I wanted to make an easy script appending facility in Mako templates.
The requirement:
<html>
<head>
<title>Some title</title>
<script>...</script>
<script>...</script>
</head>
</%def>base.mako
# -*- coding: utf-8 -*- <%! scripts = [] %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html> <head> <title>${self.title()}</title> ${self.head_scripts()} </head> <body> ${self.menu()} ${next.body()} ${self.footer()} </body> </html> ... <%def name="head_scripts()"> <% all_scripts = [] t = self while t: all_scripts = getattr(t.module, 'scripts', []) + all_scripts t = t.inherits %> % for script in all_scripts: <script src="${script}" type="text/javascript"></script> % endfor
Notice the top portion of the template. We define a list variable called scripts. At this point scripts is empty.
<%! scripts = [] %>
We render the script tags by calling the function head_scripts().
${self.head_scripts()}
my_page.mako
<%inherit file="/base.mako"/> <%! scripts = ['some_script.js'] %>
In my_page.mako, we define the variable scripts that contains the URLs. scripts is a list which lets you add any number of scripts to be appended.
<%! scripts = ['one.js', 'two.js', 'three.js'] %>
Looking back at base.mako, we have the function head_scripts() that grabs the scripts attribute in the inheritance chain . Once we have the list of all the URLs to be appended, we simply iterate and write the script tags.
<% all_scripts = [] t = self while t: all_scripts = getattr(t.module, 'scripts', []) + all_scripts t = t.inherits %> % for script in all_scripts: <script src="${script}" type="text/javascript"></script> % endfor
getattr() ensures that if any template in the chain doesn't define scripts, there will be no error.
Once base.mako is setup, you can append the script tags by just defining a list in the inheriting templates. You can use the same technique to append title, link, style and other HTML tags.
Nice!
Thanks for the pointer. Saved me a lot of pain trying to get my template inheritance set up properly.
Post new comment