Implement Views As Adapters

Implement views as adapters

Status: IsImplementedProposal

Author

JimFulton

Problem

Zope 3 has a presentation approach based on "views". Views are just "skinned" adapters. Skins provide a way to offer several variations on a user interface. A skin consists of some number (usually 2) of layers. There is a default layer and and one or more customization layers that override selected components, such as standard look at feel, from the default layer.

To support skins, we've provided a custom view-lookup API and presentation service. When someone looks up a view, the presentation service gets a skin setting from the request object, find the layers that make up the skin, and searches the layers looking for a matching adapter.

This approach has some disadvantages:

  • We have to use a Zope-specific view API. This limits the sharing of application code between systems. Other systems that don't need skins are likely to implement the view pattern using simple adapters, since views are really just adapters of objects being viewed and requests, which represent the user the object is displayed to.
  • Looking up a view usually requires an adapter lookup in multiple layers, since most components are found in the default layer, which is the last layer searched.
  • The request has to keep track of the skin to be used.

Proposal

I propose to provide skinned adapter lookup a different way:

  • Define layers as marker interfaces that extend request interfaces, most commonly, IBrowserRequest?.
  • Define skins using marker interfaces that extend their layers.

When views are defined for layers, we'll simply register them for the layers, rather than for the request type.

When we want to use a skin in a particular request, we'll simply declare the skin interface for request object.

To get a view, we'll simply get an adapter for the object (or objects) being viewed and the request.

We will keep the existing view-definition ZCML, which provides special value for views.

We will remove the presentation service and rewrite the view API to use the adapter service, with deprecation warnings.

We will need to adjust the way that skins and layers are defined.

  • It will be possible to define a layer in Python as an interface that extends a request type. This may be the preferred way to create a layer.
  • It will also be possible to use the existing layer directive to specify a layer in ZCML. When specifying a layer in ZCML, you will need to supply a base interface, using a new base attribute. For backward compatibility, it will be possible to omit the base attribute, in which case IBrowserRequest? will be assumed and a warning will be generated. Using the browser:layer directive will imply IBrowserRequest? (without a warning).

    When a layer is defined in ZCML, an interface object will be created and registered with the interface service under the layer name.

  • When a layer is used in a skin or view (or resource) definition, the layer name will be used to look up the layer from the interface service.

    Note that a layer reference in a view or skin definition can refer to layer defined in a Python module by simply giving the dotted name of the interface.

Note that view lookup will be faster under this scheme because a view lookup will require a single adapter lookup. Effectively, the layer search will be cached in the normal adapter registry caching data structures.


comments:

Another proof for the fact that everything can be solved using adaption --philikon, 2004/06/16 11:47 EST reply
I'm +1 on the proposal. The API will be simpler because I only will have to remember one set of methods. I don't expect the ZCML to change; at least that's what I read between the lines. Last but not least, I really like using marker interfaces for this. I'm a big fan of them.



( 97 subscribers )