sqlalchemy / mako

Mako Templates for Python
https://www.makotemplates.org
MIT License
353 stars 60 forks source link

Render Def into Variable #355

Closed warrenspe closed 2 years ago

warrenspe commented 2 years ago

Good day!

This is more of a question than an issue; I was wondering if there was any way to call a def, storing what it renders as a variable rather than rendering it to the output? Something like:

<%def name="test()">
    asdf
</%def>

<%
    somevar = test()
%>
bourke commented 2 years ago

That pattern works just as you've written it. This code:

<%def name="header(arg)">
    my ${arg} def
</%def>

<%def name="more()">
    <%
        more_impressive = header("more impressive")
    %>
    ${more_impressive}
</%def>

<%
    impressive = header("impressive")
%>

<p>${impressive}</p>

<p>${more()}</p>

renders this:

CleanShot 2022-03-08 at 08 51 02

warrenspe commented 2 years ago

Hello @bourke,

Thanks for the quick reply! I believe that it might not be working quite as I was expecting; I believe what's happening is when the def's are called they're being rendered rather than their output being stored in the variables. For illustration, the below:

<%def name="header(arg)">
    my ${arg} def
</%def>

<%def name="more()">
    <%
        more_impressive = header("more impressive")
    %>
    ${more_impressive}
</%def>

<%
    impressive = header("impressive")
    more_result = more()
%>

<p>${impressive}</p>
<p>${impressive}</p>

<p>${more_result}</p>
<p>${more_result}</p>

Renders the following:


    my impressive def

    my more impressive def

<p></p>
<p></p>

<p></p>
<p></p>
bourke commented 2 years ago

It's true that anything in the top level gets rendered, whether called as an expression or within a <% %> Python block. One way to achieve what you're after is to use the capture function as described here: https://docs.makotemplates.org/en/latest/filtering.html#buffering

<%def name="header(arg)">
    my ${arg} def
</%def>

<%def name="more()">
    <%
        more_impressive = header("more impressive")
    %>
    ${more_impressive}
</%def>

<%
    impressive = capture(header, "impressive")
    more_result = capture(more)
%>

<h4>${impressive}</h4>

<h3>${more_result}</h3

renders:


<h4>
    my impressive def
</h4>

<h3>

    my more impressive def

</h3>

You might also want to look at https://docs.makotemplates.org/en/latest/filtering.html#decorating as a way of capturing and enhancing a <%def>'s output.

warrenspe commented 2 years ago

That looks perfect, thanks!