how to use macros with pyramid / ZPT (Chameleon)

2019-04-01 06:16发布

问题:

I want to use macros with pyramid+ZPT engine (Chameleon).

The docs say that "A single Page Template can accommodate multiple macros." http://chameleon.readthedocs.org/en/latest/reference.html#macros-metal

Thus I defined a file macros.pt:

<div metal:define-macro="step-0">
  <p>This is step 0</p>
</div>
<div metal:define-macro="step-1">
  <p>This is step 1</p>
</div>

and a global template main_template.pt with all the html stuff defining a slot content.

and a template for my view progress.pt which uses main_template.pt to fill in the slot:

<html metal:use-macro="load: main_template.pt">
  <div metal:fill-slot="content">
    ...
    <div metal:use-macro="step-0"></div>
    ...
  </div>
</html>

So far I painfully found out, that I can not just say use-macro="main_template.pt" because Chameleon does not load templates automatically as Zope does. Thus I had to add the load: snippet before.

Coming to use-macro="step-0". This raises NameError for step-0. I tried to preload the macros.pt with something like <tal:block tal:define="compile load: macros.pt" /> but this didn't help.

How can I use macros which are gathered in a macros summary file?

回答1:

To use ZPT macros in Pyramid, you need to make the macro template itself available to the rendered template by passing the macro template, or even the macro itself, into the rendered template(excerpt from docs).

from pyramid.renderers import get_renderer
from pyramid.view import view_config

@view_config(renderer='templates/progress.pt')
def my_view(request):
    snippets = get_renderer('templates/macros.pt').implementation()
    main = get_renderer('templates/main_template.pt').implementation()
    return {'main':main,'snippets':snippets}

In the template that will be used by the renderer, you should reference the macros like this. I assume that your macro in main_template.pt containing the slot 'content' is named 'global_layout'. Change it to your name.

<html metal:use-macro="main.macros['global_layout']">
  <div metal:fill-slot="content">
    ...
    <div metal:use-macro="snippets.macros['step-0']"></div>
    ...
  </div>
</html>

A reference to a macro inside a template goes like this:

<div metal:use-macro="template.macros['step-0']">
    <div metal:fill-slot="content">
        added your content
    </div>
</div>
<div metal:define-macro="step-0">
    a placeholder for your content
    <div metal:define-slot="content">
    </div>
</div>

To get all the macros inside a template for passing them inside a view into a rendered template add this line to first code sample and extend the returned dictionary.

macros = get_renderer('templates/main_template.pt').implementation().macros

I could explain more, but look at the docs. A simple case like the one above is described here.

  • Using ZPT Macros in Pyramid

A full tutorial presents this topic as well. The second link will boost your knowledge.

  • Making a Main Template
  • Re-usable Template Macros

Afterwards the pyramid docs will provide even more details. Welcome to pyramid.