ralphtheninja
ralphtheninja

Reputation: 133228

Inject rendered content from several views in Pyramid into one base template

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.

Upvotes: 2

Views: 943

Answers (1)

Dzinx
Dzinx

Reputation: 57874

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>

Upvotes: 3

Related Questions