Metadata-Version: 1.1
Name: z3c.pluggabletemplates
Version: 0.2
Summary: Allows seperation of view code from skin templates like z3c.viewtemplate, but also allows multiple templates to be plugged into your view code.
Home-page: http://code.google.com/p/pluggabletemplates/
Author: Kevin Smith
Author-email: kevin@mcweekly.com
License: ZPL 2.1
Description: ===================
        Pluggable Templates
        ===================
        
        
        This package does two things. First, it does everything z3c.viewtemplate does
        -- seperate the view code layer from the template skin layer. Second, it
        allows an unlimited number of templates to be plugged into any view class.
        
        What's this for?
        ~~~~~~~~~~~~~~~~
        
        Making masterpages simple is hard work. Using macros is fairly complicated for
        designers to deal with. In fact they don't. Using z3c.viewtemplate with viewlets
        is fairly complicated for programmers to deal with. In fact I don't. So this
        is another evolutionary step to allow designers and programmersto work together
        without necessarily knowing or even liking each other.
        
        This work relies heavily on the working code done by Jurgen for z3c.viewtemplate.
        
        A simple masterpage implementation
        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        
        This is a simple masterpage implementation without using pluggabletemplates.
        
        browser.py::
        
        	class MyView(object):
        
        		masterpage = ViewTemplateFile('templates/masterpage.pt')
        		subpage = ViewTemplateFile('templates/content.pt')
        
        		authors = ['Roger Zelazny', 'Isaac Asimov', 'Robert Heinlien', 'J.R.R Tolkein']
        
        		def __call__(self):
        			return masterpage()
        
         templates/masterpage.pt::
        
         	<html>...
         	<body>
         	<h2>My Master Page</h2>
         	<span tal:replace="view/subpage" />
         	</body>
         	</html>
        
         templates/index.pt::
        
        	<ul>
        		<li tal:repeat="author view/authors" tal:content="author" />
        	</ul>
        
        This is a very easy to follow pattern which can be extended  fairly easily. This
        pattern runs into immediate problems when you want to change skins. Changing skins
        should be as easy as ++skin++design1 ... +++skin++design2, but to do so, all of the
        view code needs to be duplicated. Which can be done, but as soon as one piece of view
        code is changed, all the other view code has to be patched and easily falls out of
        sync.
        
        Enter viewplugs
        ~~~~~~~~~~~~~~~
        
        design1/configure.zcml::
        
        	<browser:pluggableTemplates
        		for="myapp.browser.MyView"
        		layer=".skins.Design1"
        		>
        		<template
        			name="master"
        			file="templates/masterpage.pt"
        			/>
        		<template
        			name="subtemplate"
        			file="templates/subtemplate.pt
        			/>
        	</browser:pluggableTemplates>
        
        So does this mean we'll need to duplicate all of this configuration for
        ++skin++design2?? Not necessarily::
        
        	class Design2(Design1):
        		""" Skin marker """
        
        Now you can use ++skin++design1 one as your base and simply override
        the views or templates you need to change et. al. stylesheets and
        images.
        
        
        By plugging templates into view code, each template can display each of the
        other templates::
        
        	<span tal:replace="view/template1" />
        	<span tal:replace="view/template2" />
        
        And of course all view attributes are available::
        
        	<span tal:replace="view/myattr1" />
        
        You can add as many views as you like, though, too many, and it could get recomplicated.
        
        Doctests
        ~~~~~~~~
        
        Before we can setup a view component using this new method, we have to first
        create a master template and subtemplate ...
        
          >>> import os, tempfile
          >>> temp_dir = tempfile.mkdtemp()
          >>> master = os.path.join(temp_dir, 'master.pt')
          >>> open(master, 'w').write('''<h2>Masterpage</h2><span tal:replace="view/subtemplate"/>''')
          >>> subtemplate = os.path.join(temp_dir, 'subtemplate.pt')
          >>> open(subtemplate, 'w').write('''This is the subtemplate: <span tal:replace="view/taste" />''')
          >>> from zope.publisher.browser import TestRequest
          >>> request = TestRequest()
        
          >>> from zope import interface
          >>> from z3c.pluggabletemplates.baseview import MasterView
          >>> from z3c.pluggabletemplates.pagetemplate import RegisteredPageTemplate
          >>> class IMyView(interface.Interface):
          ...     pass
          >>> class MyView(MasterView):
          ...     interface.implements(IMyView)
          ...     master = RegisteredPageTemplate( 'master' )
          ...	  taste = 'success'
          ...     subtemplate = RegisteredPageTemplate( 'subtemplate' )
        
        
          >>> view = MyView(root, request)
        
        Since the template is not yet registered, rendering the view will fail::
        
          >>> print view()
          Traceback (most recent call last):
          ...
          ComponentLookupError: ......
        
        Let's now register the template (commonly done using ZCML)::
        
          >>> from zope import component
          >>> from zope.publisher.interfaces.browser import IDefaultBrowserLayer
          >>> from z3c.pluggabletemplates.zcml import TemplateFactory
          >>> from zope.pagetemplate.interfaces import IPageTemplate
        
        The template factory allows us to create a ViewPageTemplateFile instance::
        
          >>> factory = TemplateFactory(master, 'text/html')
        
        We register the factory on a view interface and a layer::
        
          >>> component.provideAdapter(factory,
          ...            (interface.Interface, IDefaultBrowserLayer),
          ...            IPageTemplate, name="master")
          >>> mastertemplate = component.getMultiAdapter(
          ...               (view, request), IPageTemplate, name="master"  )
          >>> mastertemplate
          <zope.app.pagetemplate.viewpagetemplatefile.ViewPageTemplateFile ...>
        
          >>> factory = TemplateFactory(subtemplate, 'text/html')
        
        We register the factory on a view interface and a layer::
        
          >>> component.provideAdapter(factory,
          ...            (interface.Interface, IDefaultBrowserLayer),
          ...            IPageTemplate, name="subtemplate")
          >>> subtemplate = component.getMultiAdapter(
          ...               (view, request), IPageTemplate, name="subtemplate"  )
          >>> subtemplate
          <zope.app.pagetemplate.viewpagetemplatefile.ViewPageTemplateFile ...>
        
        Now that we have a registered template for the default layer we can call our
        view again::
        
          >>> print view()
          <h2>Masterpage</h2>This is the subtemplate: success
          <BLANKLINE>
        
        
        Cleanup
        
          >>> import shutil
          >>> shutil.rmtree(temp_dir)
        
        Revision Log
        ============
        
        * 11/03/06 initial checkin
Keywords: zope zope3 template
Platform: UNKNOWN
Classifier: Framework :: Zope3
