2

I'd like to do something like below.

I have the following routes configured:

config.add_route('home', '/')
config.add_route('foo', '/foo')

The following views:

@view_config(route_name='home', renderer='templates/home.pt')
def home_view(request):
    return {...}

@view_config(route_name='foo', renderer='templates/foo.pt')
def foo_view(request):
    return {...}

There is a base template 'templates/base.pt':

<!DOCTYPE html>
<html>
<head></head>
<body>
    Welcome ${user_id}<br>
    <a href="/foo">Foo</a><br>
    <div id="content">
        <!-- Inject rendered content here from either / or /foo --> 
    </div>
</body>
</html>

Now in my views I'd like to inject the following content into the div with id "content":

<!-- templates/home.pt -->
<div id="home-content">Home content</div>

<!-- templates/foo.pt -->
<div id="foo-content">Foo content</div>

How would I go about changing home_view and foo_view above so that they can inject their own templates (home.pt, foo.pt) into base.pt? Somehow I also need to transfer data such as ${user_id} into base.pt as well. I was playing around with the wrapper argument when defining my views, but couldn't figure out how it works.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
rtn
  • 127,556
  • 20
  • 111
  • 121

1 Answers1

3

You can achieve this in several ways (see e.g. Using ZPT Macros in Pyramid or Chameleon documentation introduction).

In your simple case, I think this is the fastest way: first, change your base.pt file to:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:tal="http://xml.zope.org/namespaces/tal"
      xmlns:metal="http://xml.zope.org/namespaces/metal">
<head></head>
<body>
    Welcome ${user_id}<br>
    <a href="/foo">Foo</a><br>
    <div id="content">
        <tal:block metal:define-slot="content">
        </tal:block>
    </div>
</body>
</html>

This defines a content slot of the Chameleon macro.

Your foo.pt could look like this:

<metal:main
    xmlns:tal="http://xml.zope.org/namespaces/tal"
    xmlns:metal="http://xml.zope.org/namespaces/metal"
    use-macro="load: base.pt">
    <tal:block metal:fill-slot="content">
        <div id="foo-content">Foo content</div>
    </tal:block>
</metal:main>

Note the use-macro="load: base.pt line. home.pt should follow the same pattern. user_id and other template variables are available to the macro, so, for example, if you set user_id to USER, /foo will render:

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head></head>
<body>
    Welcome USER<br>
    <a href="/foo">Foo</a><br>
    <div id="content">
        <div id="foo-content">Foo content</div>
    </div>
</body>
</html>
Dzinx
  • 55,586
  • 10
  • 60
  • 78
  • That looks more or less exacly what I want. I guess the different view methods would have to get a base-dict from some common method and add extra data to it before returning? (Since all templates using base.pt need to have the same basic data that base.pt will render, in this example only user_id but for my real base.pt I have more data that is common) – rtn Feb 15 '12 at 12:01
  • Always nice to be able to cash in from the community :) Thanks! – rtn Feb 15 '12 at 12:38