ZCML和ViewPageTemplateFile中的模板有什么区别

时间:2012-12-14 02:44:34

标签: python plone zope zcml

在Plone中创建BrowserView时,我知道我可以选择使用 ZCML 配置模板,如下所示:

<configure

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

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

</configure>

或者代码:

# 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)

这两种方法有什么区别吗?它们似乎都会产生相同的结果。

子问题:我知道可以导入一个BrowserView类,但通常每个人都使用BrowserPage。如果两个类之间存在显着差异怎么办?

3 个答案:

答案 0 :(得分:7)

在Plone中,只有在明确注册模板时(例如使用ZCML或Grok指令),才能自定义模板TTW(通过portal_view_customizations)。

如果您仅在__call__中定义模板,则不会在portal_view_customizations中看到它。

另外,我猜测方法中的加载模板会为每个视图实例(每个请求)从磁盘重新加载它。

答案 1 :(得分:7)

注意:要完全等效于ZCML,您应该设置index变量以指定您正在使用的模板。这样TTW定制也会起作用。

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

您可以在浏览器视图中使用的另一种模式是添加更新方法。

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

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

但这不是问题。


那有什么区别? 没有区别。浏览器视图必须是可调用的。 ZCML指令以对象具有必须返回呈现页面的索引的方式构建此可调用对象。

但是在每个调用(您的示例)上创建模板有一个区别: 您是在每次调用浏览器视图时创建模板的新实例。 类变量不是这种情况。

最后一个选项:您不需要指令

中的类参数
<configure xmlns:browser="http://namespaces.zope.org/browser">
  <browser:page
    …
    template="foo.pt"
    …
    />
</configure>

有关详细信息,请阅读the code of the directive,其中使用SimpleViewClass where src is the template name

答案 2 :(得分:1)

AFAIK,没有区别。 ZCML指令生成带有ViewPageTemplateFile的ViewClass,并在__call__上呈现模板。请参阅zope.browserpage.metaconfigure.page第132,151行。

这与您在示例中的操作完全相同:您在__call__方法中显式实例化模板。

关于子问题:根据我的理解,Zope2 / Plone背景下的显着差异并不明显。基于接口(zope.publisher.interfaces.browser.IBrowserPage),BrowserPage是您要继承的基类,因为它实现了__call__browserDefault。但是,如果您将BrowserPageBrowserView与Plone一起使用似乎并不重要。