Search code examples
templatesinheritancepyramidmako

Mako inhereting from multiple files


I have a pyramid application with multiple views each depending on a single mako template. The views are quite complicated and bug free, so I don't want to split or merge views, and by extension, the corresponding templates.

However, I would like a single view to represent all the others. Merging all the pyramid views and templates is practically not an option.

For example, I have a login view & template and a signup view & template. Now I want my root page to contain both of them. Both login and signup inherit from base.mak, which contains common scripts and style sheet imports. The following is a pictorial representation of the mako import structure I want.

        base.mak  
       /         \  
login.mak         signup.mak  
       \         /  
        root.mak  

Alternatively, I tried chaining them as such: base -> login -> signup -> root

However, I think that the views no longer talk to their respective templates.

My problem comes in when I do the 3rd chain (login.mak -> signup). I'll post analogous and extract code below, since my full code is a bit long (If more code is needed, feel free to shout).

base.mak:

<!DOCTYPE HTML>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>
            ${next.title()}
        </title> 
        #Imports

        ${next.head()}

    </head>
    <body>
        <div id = "content">
            ${next.body()}
        </div>
    </body> 
</html>

login.mak:

<%inherit file="base.mak"/>

<%def name="title()">
    ${next.title()}
</%def>

<%def name="head()">
    ${next.head()}
</%def>

<div id="login">
    <div id="message">
        ${sMessage}
    </div>

    <div id="form">
        <form action="${url}" method="post">      <--- url returned in views.py
...
</div>

${next.body()}

signup.mak:

<%inherit file="login.mak"/>

<%def name="title()">
</%def>

<%def name="head()">
</%def>

<div id="box">
...
</div>

Now my problem here is that my url returned from my views is undefined when I try to inherit as in above.

Then of course if I get this working, adding base.mak to to inherit from signup should be trivial.

I assume that there is a simple fix for this, but I can't find an example/explanation on how to do this in pyramid, where the templates actually do stuff.

Alternatively, Is there another way to bring together multiple pyramid views and templates into a single view?


Solution

  • Ok, I figured it out. One has to use mako's <%include/>, and then there is no complicated inheritance structure. So, now my files look like this:

    root.mak

    <%inherit file="base.mak"/>
    
    <%def name="title()">
        Welcome
    </%def>
    
    <%def name="head()">
    </%def>
    
    
    <%include file="login.mak"/>
    <%include file="signup.mak"/>
    

    login.mak:

    <%inherit file="base.mak"/>
    <%def name="title()">
    </%def>
    
    <%def name="head()">
        <link rel="stylesheet" type="text/css" href="${request.static_url(...
    </%def>
    
    <div id="login">
        <div id=".....
    </div>
    

    and the same structure with signup.mak. base.mak still looks the same as in the question above.

    Now, if you're using pyramid (I assume another framework will work the same), and you have views that receive and pass information from forms for example, then turn them into normal functions (without @view_config(renderer='path/file.mak') and place their functionality into the parent view function, in my case root. In other words:

    @view_config(renderer='pyramidapp:templates/root.mak',
        context=Root,
        name="")
    @forbidden_view_config(renderer='pyramidapp:templates/root.mak')
    def root(self):
        xLoginRet = login(self)
        xSignupRet = signup(self)
        #logic and functionality for both, return stuff to go to base.mak