pythonplonezopezcml

What is the difference between template in ZCML and ViewPageTemplateFile


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?


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.