Custom tag for static dependencies

104 views
Skip to first unread message

Philipp Volguine

unread,
Nov 25, 2012, 12:10:47 AM11/25/12
to mako-d...@googlegroups.com
I'd like to add a way to declare static dependencies to mako snippets that will be included into a larger template.

For example if I have a page that will include myform.mako, at the top of myform.mako could be:

<%depends js="formtojson, ajaxsubmit" css="baseformstyle, baseform" %>
<form>.....</form>

My webapp could return the actual url to these assets.
Then in the page that includes myform.mako I could have something like:

<%static_assets>
##I could include more static things here, but the files myform.mako relies on would also be shoved in here
</%static_assets>

This will let me keep pieces of the site more self contained, and let me more easily assemble larger pages from parts. Also It would be easier to manage assets in
different environments (dev or production for example)
So my question then is:
How do I go around doing this with Mako?

Does the language as of now let me do this, or do I have to dive into the source?

Michael Bayer

unread,
Nov 25, 2012, 11:27:01 AM11/25/12
to mako-d...@googlegroups.com

guess I should put this on the site, but you can navigate to all the namespaces present in a particular context, and grab whatever attributes you want.  The easiest way for namespaces to pass "configurational" information to each other is via the namespace.attr attribute, which is basically every variable name declared in <%! %> for that namespace's template.    So here is one recipe:

from mako.lookup import TemplateLookup

tl = TemplateLookup()

tl.put_string("base.mako",
"""
## base-most template, renders layout etc.
<html>
<head>
% for ns in context.namespaces.values():
    % for incl in ns.attr.includes or []:
        ${incl}
    % endfor
% endfor
</head>
<body>
${next.body()}
</body
</html>
"""
)

tl.put_string("library.mako",
"""
## library functions.

<%!
    includes = [
        '<link rel="stylesheet" type="text/css" href="mystyle.css"/>',
        '<script type="text/javascript" src="functions.js"></script>',
    ]
%>

<%def name="mytag()">
    <form>
        ${caller.body()}
    </form>
</%def>
""")

tl.put_string("index.mako",
"""
## calling template.
<%inherit file="base.mako"/>
<%namespace name="foo" file="library.mako"/>

<%foo:mytag>
    a form
</%foo:mytag>

""")


print tl.get_template("index.mako").render()

So, as far as making it more of a tag, you can do the same idea, but use a def named includes, this works too:

(in the base)

<head>
% for ns in context.namespaces.values():
    % if hasattr(ns, 'includes'):
        ${ns.includes()}
    % endif
% endfor
</head>


(in the library)

<%def name="includes()">
    <link rel="stylesheet" type="text/css" href="mystyle.css"/>
    <script type="text/javascript" src="functions.js"></script>
</%def>





--
You received this message because you are subscribed to the Google Groups "Mako Templates for Python" group.
To view this discussion on the web visit https://groups.google.com/d/msg/mako-discuss/-/GDbvUNmh_yIJ.
To post to this group, send email to mako-d...@googlegroups.com.
To unsubscribe from this group, send email to mako-discuss...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/mako-discuss?hl=en.

Michael Bayer

unread,
Nov 25, 2012, 11:55:23 AM11/25/12
to mako-d...@googlegroups.com

On Nov 25, 2012, at 11:27 AM, Michael Bayer wrote:

>
> guess I should put this on the site,

here's that

http://docs.makotemplates.org/en/latest/namespaces.html#namespace-api-usage-example-static-dependencies

Philipp Volguine

unread,
Nov 25, 2012, 7:31:50 PM11/25/12
to mako-d...@googlegroups.com
Thank you, that helped a lot!

Philipp Volguine

unread,
Dec 5, 2012, 10:45:00 PM12/5/12
to mako-d...@googlegroups.com
How would I go about using this trick for inheritance? The child template overrides the module level variables declared in it's parent.
If I do something like:

from mako.lookup import TemplateLookup
tl = TemplateLookup()
tl.put_string("base.mako",
"""
<%!
includes = ['a', 'b']
%>
${next.body()}
"""
)
tl.put_string("index.mako",
"""
## calling template.
<%inherit file="base.mako"/>
<%
    self.attr.includes.append('5')
    print self.attr.includes
%>
""")
tl.get_template("index.mako").render()

It works but the next time a different template inherits from base, the includes variable contains '5'.

PS

There's a tiny typo in the docs you put up (really awesome you did that though) http://docs.makotemplates.org/en/latest/namespaces.html?highlight=pageargs#version-one-use-namespace-attr
you need to append the '>' character to line 15 to close the </body> tag.

Michael Bayer

unread,
Dec 6, 2012, 5:34:15 PM12/6/12
to mako-d...@googlegroups.com
On Dec 5, 2012, at 10:45 PM, Philipp Volguine wrote:

How would I go about using this trick for inheritance? The child template overrides the module level variables declared in it's parent.
If I do something like:

from mako.lookup import TemplateLookup
tl = TemplateLookup()
tl.put_string("base.mako",
"""
<%!
includes = ['a', 'b']
%>
${next.body()}
"""
)
tl.put_string("index.mako",
"""
## calling template.
<%inherit file="base.mako"/>
<%
    self.attr.includes.append('5')
    print self.attr.includes
%>
""")
tl.get_template("index.mako").render()

It works but the next time a different template inherits from base, the includes variable contains '5'.

err you wouldn't want to modify self.attr.includes like that.   in general, steer clear of mutation operations.

the module level variables of each template are independent of each other.   context.namespaces only gives you templates that were pulled in via the <%namespace> tag.  For the attr of the immediate template you'd call local.attr, for the attr of the original calling template you'd call self.attr, if you're in the base and you want to iterate through from base to caller, you'd do:

ns = local
while True:
    ns = ns.context.get("next")
    if ns is None:
        break
   # do something with ns.context.attr.includes

the namespaces involved are "local", "self", "next", and "parent", we don't quite have super clean navigation through these but they're all there.

Reply all
Reply to author
Forward
0 new messages