Scan descendant template namespaces for particular attributes

102 views Asked by At

I'm trying to understand the Version One - Use Namespace.attr example for accessing descendant attributes in Mako. I have the base page template in page.html, and the index page in index.html which inherits page.html. I want to allow page.html (and page that inherits it) to specify their own Javascript and CSS files to include and allow page.html to handle rendering them.

page.html:

<!DOCTYPE html>
<%namespace name="common" file="common.html"/>
<%

# Scan for scripts and styles to include.
include_scripts = []
include_styles = []
for ns in context.namespaces.values():
    if hasattr(ns.attr, 'include_scripts'):
        include_scripts.extend(ns.attr.include_scripts)
    if hasattr(ns.attr, 'include_styles'):
        include_styles.extend(ns.attr.include_styles)

%>
<html>
  <head>
   <title>${self.attr.title}</title>
% for style in include_styles:
  ${common.style(style)}
% endfor
% for script in include_scripts:
  ${common.script(script)}
% endfor
  </head>
  <body>
    ${next.main()}
  </body>
</html>

common.html:

<%def name="script(src)">
  <script type="application/javascript" src="%{src | h}"></script>
</%def>

<%def name="style(href)">
  <link rel="stylesheet" type="text/css" href="${href | h}"/>
</%def>

index.html:

<%inherit file="page.html"/>
<%!

# Set document title.
title = "My Index"

# Set document scripts to include.
include_scripts = ['index.js']

# Set document styles to include.
include_styles = ['index.css']

%>

<%def name="main()">
  <h1>${title | h}</h1>
</%def>

This all renders the following page:

<!DOCTYPE html>


<html>
  <head>
    <title>My Index</title>
  </head>
  <body>

    <h1>My Index</h1>

  </body>
</html>

The rendered page is missing the styles and javascript includes that I'm expecting which should be:

<!DOCTYPE html>


<html>
  <head>
    <title>My Index</title>
    <script type="application/javascript" src="index.js"></script>
    <link rel="stylesheet" type="text/css" href="index.css"/>
  </head>
  <body>

    <h1>My Index</h1>

  </body>
</html>

In page.html, if I print context.namespaces I get:

{('page_html', u'common'): <mako.runtime.TemplateNamespace object at 0x1e7d110>}

Which indicates that only the imported common.html template is available and but no descendant template namespaces which inherit from page.html. How do I iterate through the inheriting template namespaces and check their attributes? I know I can use next to get the next template namespace, but how do I get the next template namespace after that if it exists?

1

There are 1 answers

0
Uyghur Lives Matter On BEST ANSWER

The code snippet in page.html to check descendent templates for the include_scripts and include_styles attributes has to traverse next of each descendant template namespace to get to the next. Using context.namespaces only appears to list the local namespaces.

import mako.runtime

# Scan for scripts and styles to include.
include_scripts = []
include_styles = []

# Start at the first descendant template.
ns = next
while isinstance(ns, mako.runtime.Namespace):
    if hasattr(ns.attr, 'include_scripts'):
        include_scripts.extend(ns.attr.include_scripts)
    if hasattr(ns.attr, 'include_styles'):
        include_styles.extend(ns.attr.include_styles)

    # NOTE: If the template namespace does not have *next* set, the built
    # in python function *next()* gets returned.
    ns = ns.context.get('next')