视图模板
项目描述
此包允许我们将视图代码和视图模板的注册分离。
为什么这是好事?
在开发需要为我们特定的应用程序开发多个客户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的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | eb28b6e7e63546309a50b2823c6b6a2b78bc5029689aa6be3dd4b41ebcba0505 |
|
MD5 | ce7671f95526904a4b8f2c7123733487 |
|
BLAKE2b-256 | d39883cf00493f463beb8043158e5f1f65356432cb70c91151b9e571b9a41c80 |