Patto and Jason,
You probably meant to write it the other way, and I'm not trying to be a nitpicker, but just to be clear, especially for the sake of anyone else reading this, I believe the opening tag for module-level blocks is
<%!
with the exclamation point FOLLOWING the percent sign, yes? Both of you, Jason and Patto, wrote it with the percent sign preceding the percent, which is likely to give errors and not do what you want.
My tests show that context.get("detail_obj").title will NOT work inside a module Python block <%! %>, because the context variable is a Python function parameter, and not available at module scope.
Here's another approach, which is the best that I can recommend, but I think that you will like it better than computing detail_title in your separate Python file and passing it in as a pre-built parameter. Try this:
## detail.html
<%inherit file="base.html" />
<%def name="detail_title()" buffered=True>
${detail_obj.title}
</%def>
<%block name="title">
<title>${detail_title()}</title>
</%block>
This gives you the maximum flexibility so that you can do normal variable things like
${detail_title() + " (the title is " + unicode(len(detail_title())) + " characters long)"
or
${detail_title().upper()}
This is the way I recommend.
Remember that normally, a def function writes its output directly to the output stream with context.write() rather than returning the output as the string result of the function call, and after writing to the output stream, it returns an empty string (see
http://docs.makotemplates.org/en/latest/filtering.html#buffering). The buffered=True attribute stops Mako from doing this and returns the output as the result of the string, as our (or at least my) intuition wants to believe. This seems closest to the behavior of a variable, so this is probably what you want.
Keep in mind, that the object's title attribute is computed EVERY TIME the function is called, not just once and stashed in a variable. Clearly it's more efficient to do it way I first suggested of computing the title once and passing that in as a template argument.
If you want to preserve the type of the variable (not automatically convert it to a string) here's how I would do it. Suppose there is the template parameter named object1. Suppose you need to do some operations on it which give you another object that can't be losslessly represented as a string. Let's say object1 is the parameter to the template and detail_object is the thing to be computed. Then do this instead:
<%def name="detail_object()"> ## no buffered attribute
<% return some_function(object1.operation1(2498).operation2({"keep": "going"})) %>
</%def>
Instead of converting the expression to a string as ${} always does, it returns the value directly with its original type and such.
Then you can do
${detail_object().title}
or some other final operation on the object after the call. Remember again, that all the computation is repeated for each call to detail_object().
I believe it's better form it save heavy computations for the Python files and just do mostly cherry-picking stuff in the Mako templates.
I think this should give you some ideas to work with.
Happy Mako-ing!
—Christopher