跳转到主要内容

视图模板

项目描述

此包允许我们将视图代码和视图模板的注册分离。

为什么这是好事?

在开发需要为我们特定的应用程序开发多个客户UI的可定制应用程序时,我们注意到皮肤和层之间有一个细微但清晰的区别。层包含准备数据以进行展示输出的逻辑,即视图类。另一方面,皮肤包含生成UI的资源,例如模板、图像和CSS文件。

现有基础设施的问题在于代码、模板和层都硬链接在一个视图组件的zcml配置指令中 – 页面、内容提供者、视图组件。此包将这个三元组 – 代码、模板、层 – 分离成两个对,代码/层和模板/皮肤。由于皮肤和层在物理上是相同的组件,因此没有引入额外的组件。

详细文档

ViewTemplate

此包允许我们将视图代码和视图模板的注册分离。

为什么这是好事?

在开发需要为我们特定的应用程序开发多个客户UI的可定制应用程序时,我们注意到皮肤和层之间有一个细微但清晰的区别。层包含准备数据以进行展示输出的逻辑,即视图类。另一方面,皮肤包含生成UI的资源,例如模板、图像和CSS文件。

现有基础设施的问题在于代码、模板和层都硬链接在一个视图组件的zcml配置指令中 – 页面、内容提供者、视图组件。此包将这个三元组 – 代码、模板、层 – 分离成两个对,代码/层和模板/皮肤。由于皮肤和层在物理上是相同的组件,因此没有引入额外的组件。

在使用此新方法设置视图组件之前,我们必须首先创建一个模板 …

>>> import os, tempfile
>>> temp_dir = tempfile.mkdtemp()
>>> template = os.path.join(temp_dir, 'demoTemplate.pt')
>>> open(template, 'w').write('''<div>demo</div>''')

以及视图代码

>>> from zope.publisher.browser import TestRequest
>>> request = TestRequest()
>>> from zope import interface
>>> from z3c.viewtemplate.baseview import BaseView
>>> class IMyView(interface.Interface):
...     pass
>>> class MyView(BaseView):
...     interface.implements(IMyView)
>>> view = MyView(root, request)

由于模板尚未注册,渲染视图将失败

>>> print view()
Traceback (most recent call last):
...
ComponentLookupError: ......

现在让我们注册模板(通常使用ZCML完成)

>>> from zope import component
>>> from zope.publisher.interfaces.browser import IDefaultBrowserLayer
>>> from z3c.viewtemplate.zcml import TemplateFactory
>>> from zope.pagetemplate.interfaces import IPageTemplate

模板工厂允许我们创建ViewPageTeplateFile实例。

>>> factory = TemplateFactory(template, None, 'text/html')

我们在视图接口和层上注册该工厂。

>>> component.provideAdapter(factory,
...            (interface.Interface, IDefaultBrowserLayer),
...            IPageTemplate)
>>> template = component.getMultiAdapter(
...               (view, request), IPageTemplate)
>>> template
<zope...viewpagetemplatefile.ViewPageTemplateFile ...>

现在我们已为默认层注册了模板,可以再次调用我们的视图。视图是一个内容提供者,所以在调用其更新方法之前会触发一个BeforeUpdateEvent。

>>> events = []
>>> component.provideHandler(events.append, (None,))
>>> print view()
<div>demo</div>
>>> events
[<zope.contentprovider.interfaces.BeforeUpdateEvent object at ...>]

现在我们在视图的特定接口上注册一个新模板。

>>> myTemplate = os.path.join(temp_dir, 'myViewTemplate.pt')
>>> open(myTemplate, 'w').write('''<div>IMyView</div>''')
>>> factory = TemplateFactory(myTemplate, None, 'text/html')
>>> component.provideAdapter(factory,
...            (IMyView, IDefaultBrowserLayer),
...            IPageTemplate)
>>> print view()
<div>IMyView</div>

我们还可以用设置了调试标志的方式渲染视图。

>>> request.debug.sourceAnnotations = True
>>> print view()
<!--
==============================================================================
...myViewTemplate.pt
==============================================================================
--><div>IMyView</div>
>>> request.debug.sourceAnnotations = False

可以直接提供模板。

我们创建了一个新模板。

>>> viewTemplate = os.path.join(temp_dir, 'viewTemplate.pt')
>>> open(viewTemplate, 'w').write('''<div>view</div>''')
>>> from zope.app.pagetemplate.viewpagetemplatefile import ViewPageTemplateFile
>>> class MyViewWithTemplate(BaseView):
...     interface.implements(IMyView)
...     template = ViewPageTemplateFile(viewTemplate)
>>> templatedView = MyViewWithTemplate(root, request)

如果我们渲染这个视图,我们得到的是原始模板,而不是注册的模板。

>>> print templatedView()
<div>view</div>

宏的使用。

>>> macroTemplate = os.path.join(temp_dir, 'macroTemplate.pt')
>>> open(macroTemplate, 'w').write('''
...   <metal:block define-macro="macro1">
...     <div>macro1</div>
...   </metal:block>
...   <metal:block define-macro="macro2">
...   <div tal:content="options/foo">macro2</div>
...   </metal:block>
...   ''')
>>> factory = TemplateFactory(macroTemplate, 'macro1', 'text/html')
>>> print factory(view, request)()
<div>macro1</div>

由于可以为视图小部件传递选项,让我们验证宏是否也可以这样做。

>>> factory = TemplateFactory(macroTemplate, 'macro2', 'text/html')
>>> print factory(view, request)(foo='bar')
<div>bar</div>

为什么我们没有使用来自zope.formlib包的命名模板呢?

尽管命名模板允许我们将视图代码与模板注册分离,但它们不能注册到特定的层,这使得使用命名模板实现多个皮肤变得不可能。

页面模板

对于最简单的使用,我们提供了一个类似于ViewPageTemplateFile或NamedTemplate的RegisteredPageTemplate。

RegisteredPageTemplate允许我们使用新的模板注册系统,包括所有现有的实现,如zope.formlib和zope.viewlet。

>>> from z3c.viewtemplate.pagetemplate import RegisteredPageTemplate
>>> class IMyUseOfView(interface.Interface):
...     pass
>>> class UseOfRegisteredPageTemplate(object):
...     interface.implements(IMyUseOfView)
...
...     template = RegisteredPageTemplate()
...
...     def __init__(self, context, request):
...         self.context = context
...         self.request = request

将“template”属性定义为“RegisteredPageTemplate”时,在调用时会执行对注册模板的查找。注意,现在不再需要从BaseView派生视图!

>>> simple = UseOfRegisteredPageTemplate(root, request)
>>> print simple.template()
<div>demo</div>

由于演示模板被注册为任何(“None”)接口,我们在渲染新视图时看到的是演示模板。我们特别为新视图注册一个新模板。另外请注意,“macroTemplate”是在这个测试的早期创建的。

>>> factory = TemplateFactory(macroTemplate, 'macro2', 'text/html')
>>> component.provideAdapter(factory,
...            (IMyUseOfView, IDefaultBrowserLayer),
...            IPageTemplate)
>>> print simple.template(foo='bar')
<div>bar</div>

变更

0.4.1 (2010-12-12)

  • 修复了如果在模板中找不到宏时异常处理的问题。

  • 修复了测试,以便它们可以在Windows上成功运行。

  • 使用Python的doctest模块而不是已废弃的zope.testing.doctest。

  • 移除了ZCML slugs和ZPKG。

0.4.0 (2008-11-05)

  • 添加了对TAL调试标志的支持。

0.3.2 (2007-11-01)

  • 修复了包元数据。

0.3.1 (2007-10-31)

  • 错误修复:选项未传递给宏模板。

0.3.0 (2007-09-27)

  • 将请求添加到BeforeUpdateEvent,这需要最新的zope.contentprovider包。

  • 不再有开发版本。

0.2 (2007-05-01)

  • 在基本视图中触发BeforeUpdateEvent。这需要zope 3.4。

项目详情


下载文件

下载适合您平台的文件。如果您不确定要选择哪个,请了解更多关于安装包的信息。

源分布

z3c.viewtemplate-0.4.1.tar.gz (9.5 kB 查看散列

上传时间

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面