Question

When creating a BrowserView in Plone, I know that I may optionally configure a template with ZCML like so:

<configure

    xmlns:browser="http://namespaces.zope.org/browser"
    >

    <browser:page
        …
        class=".foo.FooView"
        template="foo.pt"
        …
        />

</configure>

Or alternatively in code:

# foo.py
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.publisher.browser import BrowserPage


class FooView(BrowserPage):
    """
    My View
    """

    def __call__(self):
        return ViewPageTemplateFile('foo.pt')(self)

Is there any difference between the two approaches? They both appear to yield the same result.

Sub-question: I know there is a BrowserView class one can import, but conventionally everyone uses BrowserPage. What if any significant differences exist between the two classes?

Was it helpful?

Solution

Note: To be fully equivalent to ZCML you should set the index variable to specify which template you are using. That way the TTW customization will work too.

# foo.py
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from zope.publisher.browser import BrowserPage
class FooView(BrowserPage):
    index = ViewPageTemplateFile('foo.pt')

One other pattern you can use with a browser view is adding an update method.

class FooView(BrowserPage):
    index = ViewPageTemplateFile('foo.pt')
    def __call__(self):
        self.update()
        return self.index()

    def update(self):
        self.portal_catalog = ...  # initialize code

But this is not the question.


So what is the difference? There is no difference. A browser view must be a callable. The ZCML directive builds this callable in a way the object has an index which must return the rendered page.

But creating the template on each call (your example) there is one difference: you are creating a new instance of the template on each call of the browser view. This is not the case with class variable.

One last option: You don't need a class argument in the directive

<configure xmlns:browser="http://namespaces.zope.org/browser">
  <browser:page
    …
    template="foo.pt"
    …
    />
</configure>

For more information, you should read the code of the directive, which uses SimpleViewClass where src is the template name.

OTHER TIPS

In Plone, you can customize the template TTW (via portal_view_customizations) only when the template is registered explicitly (e.g. using ZCML or Grok-directives).

If you define template only in your __call__, you won't see it in portal_view_customizations.

Also, I'd guess that loading template within a method would reload it from the disk for every view instance (every request).

AFAIK, there is no difference. The ZCML directive generates a ViewClass with a ViewPageTemplateFile and renders the template on a __call__. See zope.browserpage.metaconfigure.page lines 132, 151.

That is exactly the same you do in your example: you explicitly instantiate the template in your __call__ method.

As to the subquestion: From my understanding, the significant differences are not apparent in the context of Zope2/Plone. Based on the interface (zope.publisher.interfaces.browser.IBrowserPage), the BrowserPage is the base class you want to inherit from, since it implements __call__ and browserDefault. Yet, it does not seem to matter if you use BrowserPage or BrowserView with Plone.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top