Introduction

As we saw in the first approach, the renderers are the very heart of the whole Structured Document system. Even if the concept sounds quite simple, the implementation uses a lot of cutting-edge technologies, including an extensive use of zope3 components.

Learning by doing

Where to look for

Renderers basics are defined in sd.rendering. They are developped and used in sd.app.rendering

Give me facts : what a renderer truly is

  • A multi adapter on an object and a browser request
  • A python class generated from several mixins classes and a base class (see Renderer registration process)

According to the description above, a renderer is a BrowserPage with extra base classes.

Declaring a renderer

Renderers can be registered using ZCML. There are two possible registrations : chapter and paragraph renderers. We'll see them in details. But let's take it step by step.

Using the right namespace and including the necessary package

The registration is done using two statements : paragraphRenderer and chapterRenderer. They are defined in sd.app.renderering, using meta directives (see meta.zcml). Declaring a rendering will require us to use the correct namespace :

xmlns:sd="http://namespaces.zope.org/sd"

... Then include the definition package in our project.

<include package="sd.app.rendering" />

Renderer commons

A chapter and paragraph renderers are very similar. It can be generalized by the following schemas :

<chapterRenderer
  name="minimalistic_renderer"
  description="it only uses a template to renderer"
  targets="path.to.interface"
  template="mytemplate.pt"
  />
<chapterRenderer
  name="complete_renderer" 
  description="A demo view"
  renderer="path.to.custom.class"
  template="path/to/template"
  targets="path.to.content.interface"
  folderish="True"
  filtering="path.to.some.interface"
  />

A real-world example

Taken from the sd.plugins module :

<configure xmlns="http://namespaces.zope.org/sd">

  <include package="sd.app.rendering"/>

  <paragraphRenderer
      name="simple_video_renderer" 
      targets="p4a.video.interfaces.IVideoEnhanced" 
      description="Plone4Artists Video Renderer" 
      template="p4avideo_paragraph.pt"
      renderer=".video_renderer.P4AVideoRenderer"
      />

</configure>

Fields

see the metadirectives file for complete informations

name : Python identifier

The unique name of the renderer. This name is the msgid used during the internationalization. This field is optional. If not provided, the default value is "default". Of course, as the name is unique, you can have only one "default renderer.

description : Text

This is the text displayed in the layout selection drop down menu in English. This is injected as the generated renderer docstring.

renderer : Dotted class path

The dedicated class used for the rendering. This class is only optional. A default renderer is already provided. See Renderer registration process below for more information

template : Filesystem relative path

The template used in the rendering process.

macro : Python identifier

Limits the rendering to the given macro, existing within the specified template.

targets : List of dotted interfaces paths

The renderer will be available for the content types implementing one of these interfaces.

folderish : Boolean

Defines if the renderer needs to be aware of the rendered item's content. This default is True by default for the chapterRenderer and False for the paragraphRenderer. Therefore, the explicit declaration is optional

filtering : Dotted interface path

If the renderer is folderish (see above), filtering can be used to filter the fetched content by restricting the query to the given interface. This field is optional.

Renderer registration process

On runtime, when the ZCML is read, the renderer is created out of python classes mixing. Then, it is registered as a multi adapter in the zope component registry, under the specified name.

The classes mixed are :

chapterRenderer

1. sd.rendering.base.ChapterStructuredRenderer

2. sd.rendering.base.FolderishRenderer unless folderish is explicitly set to False

3. the class defined in the renderer zcml definition under renderer

paragraphRenderer

1. sd.rendering.base.ParagraphStructuredRenderer

2. sd.rendering.base.FolderishRenderer if folderish is explicitly set to True

3. the class defined in the renderer zcml definition under renderer

Example of renderer custom class

Example of a renderer that could be used for an ATNewsItem. It provides an helper attribute to display the formated image tag.

class ATNewsItemRenderer(object):
    """Base class for an atnewsitem renderer.
    """
    @property
    def image(self):
        return self.context.tag(scale='thumb')

Retrieving a renderer

Renderers are multi adapters. They adapt the object (implementing the interface defined in targets) and the request. Retrieving a renderer is simple. You only need to precise the kind of renderer you want to fetch by specifying the provided interface and its name. sd.rendering defines the provided interfaces : IChapterRenderer, IParagraphRenderer.

Code

queryMultiAdapter((object, self.request),
                  IChapterRenderer,
                  name = "my_nice_renderer")

URL

http://path.to.portal/item/@@name-of-the-renderer