Nav links

Quick links

Local sites in Five

Intro

Zope 3 has a concept of local sites and site managers. They allow one to locally override component registrations and have components and their configuration be persisted in the ZODB as well as managed through the web interface.

Five 1.5 supports two distinct and slightly incompatible versions of local site support. The first one, (here known as "old" sites) was introduced in Five 1.3 and is based on Zope 3.2s site implementation. But the site implementation in Zope 3.2 was overly complicated, and for 3.3 it was refactored, and Five 1.5 contains support for this new local site support as well (known as "new" sites).

For documentation of how to use local sites, see the Zope 3.3 documentation. This document is mostly about how the implementation of the old sites work, and how to migrate from Five 1.3 and 1.4.

Migration from old sites to new sites

New sites are based on Zope 3.3s new site managers and persistent component registries. Old sites are based on specific Five implementation of site managers, and keeps utilities in a folder called "utilities".

They are used basically the same, but they are created differently, and also, when you look up a utility with getUtility or queryUtility, in old sites, the utility will have an acquicition context, while in the new sites it will not.

Setting up the site

The old setup of a site was done by marking the class of the site as a possible site with five:localsite, and then either manually through the ZMI or programmatically through enableLocalSiteHook(site) turn it into a site.

The new setup involves calling enableSite(site) and createing and setting a site manager. The simplest way to do this manually is to go to the "components.html" view of the object you want to make a site, and press the "Make site" button. The easist way to do this programmatically, is to look up the "components.html" view on the site, and calling view.makeSite():

components_view = queryMultiAdapter((self.context, self.request),
Interface, 'components.html')

System Message: WARNING/2 (<string>, line 52)

Definition list ends without a blank line; unexpected unindent.

components_view.makeSite()

As any ObjectManager can be a site there is no longer any need to specially mark the class as being a possible site.

Registering local utilities

The old usage was to get the site manager, either throgh adapting with IFiveUtilityRegistry(site) or by calling getSiteManager(). You could then register the utilities with sitemanager.registerUtility(interface, utility)

The new way is to call getSiteManager().registerUtility(object, provided). Note that in the old way, the first parameter is the interface name, and the second the actual utility object, but in the new way, it is the other way around.

Migrating the actual sites

Go to the object of the site, and add "manage_site.html" to the URL to open the old site management view. There you have a button "Migrate to Five.component". Press it to migrate the site.

Experimental forwards compatibility

If you have software using the old sites, and software using the new sites, there is sligthly experimental support to make software expecting new sites to work with old sites. Nothing is promised with this, as it is largely untested. The best thing to do is without a doubt to convert your old site software and your old sites to use new sites.

Old site implementation details

The rest of this document documents the details of the old site implementation. Everything from here on concerns only the old implementation and is of mainly hysterical interest.

By default, Zope 3 has a global site which is configured through ZCML. It provides the fallback for all component look-up. Local sites are typically set during traversal, when the traverser encounters an ISite object. The last encountered ISite wins. Component look-up will cascade through all the sites in the hierarchy and fall back to the global site where it can finally fail.

Five also supports local sites, however by default only local utilities. Local adapters, such as ZODB-based views, could be supported with a custom implementation of the local site manager and local adapter registry. This is not the focus of local sites in Five, though.

Turning possible sites into sites

Five uses the same technique as Zope 3 for determining local sites: sites are found during URL traversal. However, since the Zope 2 ZPublisher doesn't emit the necessary events by default, Five needs to set a BeforeTraverse hook on site objects.

Setting this hook needs to be done an object-per-object basis and can be performed through the manage_site.html browser page. This view operates on IPossibleSite objects (in other words, objects that can be sites but aren't yet). It sets the traversal hook on the object and then marks it with the ISite interface to indicate that it is a real site now, not just a possible site.

Note that unlike the Zope 3 equivalent of this view, it does not set the site manager to site; it is assumed that the site already knows how to get its site manager.

Custom site implementations

Anything can be a site, there are no restrictions (sites don't have to be folders, for examples). Sites can also be nested. For all the Component Architecture cares, every object in your URL graph could be a site.

The only requirement are two interfaces:

IPossibleSite

Objects that can potentially be turned into a site need to provide this interface. That requires them to have a setSiteManager() and getSiteManager() method for setting and getting the local site manager of that site. The site manager is the registry that takes care of local component look-up.

IFiveSiteManager

This interface is a slight extension of the IServiceService or ISiteManager interface, respectively (the former in Zope X3 3.0, the latter in later versions). It defines the API of a local site manager that is to be used in a Five environment. The site's getSiteManager() method should return an object providing this interface.

Five's default site manager

If you want to instantly make your custom class an IPossibleSite implementation, you can use a default mix-in class from Five, e.g.:

class MySite(OFS.Folder, Products.Five.site.localsite.FiveSite):
    pass

This default implementation of IPossibleSite features a site manager implementation that knows how to register and look-up local utilities. It does so by adapting the site to IFiveUtilityRegistry.

The default adapter for this local utility registry simply stores the utilities in a standard OFS Folder on called utilities on the site object. You probably want to exchange that simple behaviour with something that works better in your application. You can do so by plugging in your own utility registry adapter, e.g.:

<adapter for=".interfaces.IMySite"
         provides="Products.Five.site.interfaces.IFiveUtilityRegistry"
         fatory=".module.MyUtilityRegistry" />

All this implementation needs to do is comply with the IFiveUtilityRegistry interface, which essentially means the standard utility look-up methods like queryUtility(), getUtilitiesFor(), etc.

Turning existing classes into possible sites

If you cannot or do not want to modify existing classes to mix in the FiveSite class, you can also use a structured monkey patch via ZCML:

<five:localsite class=".module.MyClass" />

This makes MyClass an IPossibleSite and sticks FiveSite's getSiteManager() and setSiteManager() methods on the class as well. You can also tell it to use a different site implementation's methods for the monkey patch:

<five:localsite class=".module.MyClass"
                site_class=".module.MySiteImpl" />

Just make sure that this class implements IPossibleSite.