• BU Home | 
  • News | 
  • Events | 
  •  | 
  •  

Web Services Wiki

Welcome Guest: Login

Overview of SilvaLayout-based Templates

SilvaLayout is an extension product of Silva to support development of website templates from filesystem products utilizing Zope3 view/skin functionality.

The best place to learn about Zope 3 is the book, "Web Component Development with Zope 3".  Zope 3 is a very fundamental shift from Zope 2 in how web components are developed.

The best place to get an overview of using SilvaLayout is to read that products README.txt, which is in Products/SilvaLayout, or you can read the svn trunk version.

SilvaLayout Components

There are three main components of a SilvaLayout template:

  1. View page template and possibly macros

    • The html templates for the layout
  2. Python code:

    • class definition for the skin
    • view class (helper functionality for the view)
  3. ZCML configuration

    • registration of the skin and public page view

View Page Template / macros

According to "Web Component Development with Zope 3", the standard practice when creating layouts/skins is to separate the layout into a set of base macros, and page templates which utilize the macros.  This may be overkill, and is a bit difficult to understand, but here's how they work.

Base Macros

BaseMacros is a python class which extends BrowserView.  It contains a mapping of macro names to macro page templates.  Suppose we have a macro for public web pages called 'basemacros.pt'.  Here's the class:

class BaseMacros(BrowserView):
    template = ViewPageTemplateFile('basemacros.pt')
    def __getitem__(self, key):
        return self.template.macros[key]

This class is registered as a browser:view in zcml for ISilvaObject (so any silva-based content object can use these base macros):

<browser:view
 for="Products.Silva.interfaces.ISilvaObject"
 name="base_macros"
 class=".base.BaseMacros"
 permission="zope2.View"
 layer="Products.SilvaLayout.browser.silvadefault.skin.ISilvaDefault"
 />

This base_macros is accessible within the SilvaDefault layout.  Be careful about naming.  If an additional base_macros was registered in a layer which extends ISilvaDefault, Zope 3 name resolution appears to resolve the ISilvaDefault base_macros first.  That seems backwards to me, but there it is.

The way Bethel is using this method, the base macro contains a single macro which renders the minimum for a public page and defines slots for public views to place content.

Public View Template

The public view template is a page template which uses the base page macro, and overrides any slots to alter the rendering of the page.  Common slots are:

  • headers, to insert stylesheets, javascript, etc
  • title, to override the default page title
  • body, to render the body of the template

Python Code

Skin definition

The skin is a zope3 interface which extends IBrowserSkinType.  Skin interfaces are used to tie zcml components (views, resourceDirectories, etc.) into layers.

The base SilvaLayout skin is: Products.SilvaLayout.browser.silvadefault.skin.ISilvaDefault .  Any skin for a new SilvaLayout-based layout should extend this one.  Example:

from Products.SilvaLayout.browser.silvadefault.skin import ISilvaDefault
class IBethelBU(ISilvaDefault):
    """BU template"""
View Class

The python view class contains the business logic and helper code for the template.  SilvaLayout has two view classes, both extending from a base view class:

  • SilvaView (BrowserView)

    • Content
    • Container

Note that SilvaView extends BrowserView.  All view classes need to extend from this main class.  In the Zope2/Five (zope3 integration) world, this class is Products.Five.BrowserView.

SilvaView contains a number of business-logic helper methods.  Some of the useful ones for Bethel's templates are: title, is_preview_view, render, render_public_preview, and metadata.  It is best, however, to inspect the source directly (Products.SilvaLayout.browser.silvaview), as it contains the best descriptions for this class.

The Content class provides additional functionality to support HTTP Put requests (i.e. saving content using kupu).  Containers have functionality for public and preview rendering of folders. 

When new layouts are created which add business logic, be sure to use the following paradigm:

  • MyCustomView

    • additional business logic to support the new layout goes in this class
  • CustomContainer(MyCustomView, Container)
  • CustomContent(MyCustomView,Content)

ZCML Configuration

The zcml configuration, located in configure.zcml, ties everything togethor.  The skin needs to be registered as an interface, the public view(s) need to be registered as browser:pages, and any resources or resourceDirectores are also registered in this way.
Taking the SilvaDefault skin as an example, the interface is registered like:

  <interface
    interface=".skin.ISilvaDefault"
    type="zope.publisher.interfaces.browser.IBrowserSkinType"
    name="SilvaDefault"
  />

There are two public views, one for IContent objects and the other for IContainer objects.  Their primary difference is the view class:

  <browser:page
    name="index.html"
    for="Products.Silva.interfaces.IContent"
    class="Products.SilvaLayout.browser.silvaview.Content"
    template="maintemplate.pt"
    permission="zope2.View"
    layer=".skin.ISilvaDefault"
  />

  <browser:page
    name="index.html"
    for="Products.Silva.interfaces.IContainer"
    class="Products.SilvaLayout.browser.silvaview.Container"
    template="maintemplate.pt"
    permission="zope2.View"
    layer=".skin.ISilvaDefault"
  />

A resource directory is registered this way:

  <browser:resourceDirectory
    name="images"
    directory="images"
    permission="zope2.Public"
    layer=".skin.ISilvaDefault"
  />

Note that all of the pages and the resourceDirectory are registered under the ISilvaDefault layer.  This is very important.  If the layer attribute was omitted, these view would apply to _all_ objects.  The use of skins and layers enable browser:pages, resourceDirectories, etc. to only be accessible through those objects which are using that skin/layer.

Preview Views

The preview view, accessed via appending '/preview_html' onto the public url, is registered only in the ISilvaDefault layer.  This is a generic view which sets a request variable to indicate the template should render the preview/editable content and then looks up and calls the public @@index.html view. The request variable is "silva_view_mode" and the value is "preview".  If the layout's view class inherits SilvaView, then preview access is checked by calling "view.is_preview_view" from within the public template.

The public index.html view should display the previewable/editable content and title.  This can be done using the following pattern:

<tal:def  define="global content python:view/render;
                  global title view/get_title" />

The method view/render calls back to is_preview_view.  The view/get_title method similarly does this, and this defined like:

    def get_public_or_preview_title(self):
        if self.is_preview_view():
            return self.context.get_title_or_id_editable()
        else:
            return self.context.get_title_or_id()