Tuesday, February 10, 2009

Defining and accessing macros located in browser:page template

The case: I want to define a simple browser page (let's name it "mypage") for a page template where I defined some metal macros (in my case it is a template for an archetypes field). My product does not provide a skin for portal_skins, I don't want to add a layer and all the generic setup stuff just for a single template. I'm using plone 3.1.

The problem: @@mypage/macros does not work as legacy portal_skins page templates used to.

Solution: define a simple class like this:
from Products.Five import BrowserView

class MacrosView(BrowserView):

@property
def macros(self):
return self.index.macros
The ZCML for "mypage":
<browser:page
for="*"
name="mypage"
class=".macros.MacrosView"
template="mypage.pt"
allowed_attributes="macros"
permission="zope.Public" />
There could be a better, less verbose solution (like providing a meta definition for zcml, in order to avoid declaring "class" and "allowed_attributes"). We could also patch Five BrowserView.

In my case I have been able to use mypage as a template for my archetypes widget:
MyWidget(macro="@@mypage",)
Compared to legacy PT you will loose some builtins (like python: test()), but that kind of logic should be (easily) moved into a dedicated view class. This is noticeable in the case you are customizing an old template (like archetypes/widgets/file.pt ;-))

Dunno if it is the "right way of doing things", at least it worked-for-me(tm).

2 comments:

davisagli said...

Five already does this for template-only browser views registered using browser:page. (See ViewMixinForTemplates in Products.Five.browser.metaconfigure)

BM said...

@davisagli: the code you are refering to juste defines "__getitem__".

This means you can get the view (view = context.restrictedTraverse('@@mypage')) and get the macros like this: view['macros']. You may even traverse directly to the macros.

But you cannot do "view.macros" (attribute access). Unfortunatly, that's what archetypes is doing when looking for macros (look at the code in Archetypes/generator/widget.py).