跳转到主要内容

HTML布局引擎

项目描述

HTML布局引擎

此软件包实现了一个基于静态HTML文档的页面渲染模型,该模型通过将内容提供者定义映射到HTML文档树中的位置来从外部动态化。这被称为“布局”。

利用组件架构提供扩展点,允许广泛的应用。支持使用zope.contentprovider渲染方案(更新/渲染)进行两阶段渲染。

静态资源(HTML文档中引用的图像、样式表和JavaScript文件)包括碳副本,并作为浏览器资源发布(请参阅zope.app.publisher.browser)。

优势

  • 无需模板语言

  • 支持两阶段渲染

  • 与创意工作流程集成

  • 灵活的扩展点

操作步骤

布局和区域

让我们先实例化一个布局。为了这个演示,我们将手动进行;通常这通过包含的ZCML指令 <browser:layout> 来完成。

>>> from z3c.layout.model import Layout
>>> layout = Layout(
...     "test", "%s/templates/default/index.html" % test_path, "test")

注册资源目录。

>>> import zope.configuration.config as config
>>> context = config.ConfigurationMachine()
>>> from zope.app.publisher.browser import resourcemeta
>>> resourcemeta.resourceDirectory(
...     context, "test", "%s/templates/default" % test_path)
>>> context.execute_actions()

布局通过定义一个或多个区域来变得动态。它们使用xpath表达式和插入模式(“替换”、“追加”、“前置”、“在...之前”或“在...之后”)映射到HTML位置。

区域可以直接指定内容提供者的名称,或者可能依赖于适配来产生内容提供者组件。我们将研究这两种方法。

>>> from z3c.layout.model import Region

首先,我们定义一个标题区域,其中我们直接指定内容提供者的名称。

>>> title = Region("title", ".//title", title=u"Title", provider="title")

然后是一个内容区域,我们将其留给内容提供者进行组件适配。

>>> content = Region("content", ".//div", "Content")

为了将它们注册到布局中,我们只需将它们添加即可。

>>> layout.regions.add(title)
>>> layout.regions.add(content)

让我们定义一个上下文类。

>>> class MockContext(object):
...     interface.implements(interface.Interface)

我们需要提供一个通用的适配器,它可以为那些没有直接指定内容提供者的区域提供内容提供者。作为一个例子,我们将定义一个适配器,该适配器尝试查找与区域同名的内容提供者。

>>> from z3c.layout.interfaces import IContentProviderFactory
>>> class EponymousContentProviderFactory(object):
...     interface.implements(IContentProviderFactory)
...
...     def __init__(self, region):
...         self.region = region
...
...     def __call__(self, context, request, view):
...         name = self.region.name
...         return component.getMultiAdapter(
...            (view.context, request, view), IContentProvider, name)
>>> from z3c.layout.interfaces import IRegion
>>> component.provideAdapter(
...     EponymousContentProviderFactory, (IRegion,))

渲染

在我们能够渲染布局之前,我们需要为两个区域注册内容提供者。我们将使用模拟类进行演示。

>>> from zope.contentprovider.interfaces import IContentProvider
>>> class MockContentProvider(object):
...     interface.implements(IContentProvider)
...
...     __name__ = u""
...
...     def __init__(self, *args):
...         pass
...
...     def update(self):
...         pass
...
...     def render(self):
...         return self.__name__
...
...     def __repr__(self):
...         return "<MockContentProvider '%s'>" % self.__name__
>>> from zope.publisher.interfaces.browser import IBrowserRequest
>>> from zope.publisher.interfaces.browser import IBrowserView
>>> component.provideAdapter(
...     MockContentProvider, (MockContext, IBrowserRequest, IBrowserView),
...     name="title")
>>> component.provideAdapter(
...     MockContentProvider, (MockContext, IBrowserRequest, IBrowserView),
...     name="content")

让我们实例化布局浏览器视图。我们必须定义上下文并设置请求。

>>> from zope.publisher.browser import TestRequest
>>> context = MockContext()
>>> request = TestRequest()

我们需要请求是可注解的。

>>> from zope.annotation.attribute import AttributeAnnotations
>>> component.provideAdapter(
...     AttributeAnnotations, (TestRequest,))

视图期望上下文能够适配到 ILayout

>>> from z3c.layout.interfaces import ILayout
>>> component.provideAdapter(
...     lambda context: layout, (MockContext,), ILayout)
>>> from z3c.layout.browser.layout import LayoutView
>>> view = LayoutView(context, request)

验证布局视图是否能够访问这些提供者。

>>> view.mapping
{'content':
 (<Region 'content' .//div (replace) None>, <MockContentProvider 'content'>),
 'title':
 (<Region 'title' .//title (replace) 'title'>, <MockContentProvider 'title'>)}

现在来看实际输出。

>>> print view()
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<link rel="stylesheet" href="test/main.css" type="text/css" media="screen">
<title>title</title>
</head>
<body>
    <div id="content">content</div>
  </body>
</html>

转换

为了支持在编译时使用 Python 对静态 HTML 文档进行转换的特殊情况,可以定义一个或多个转换。

>>> from z3c.layout.model import Transform

让我们添加一个转换,将语言设置添加到 <html>-标签中。

>>> def set_language(node):
...     node.attrib["lang"] = "en"
>>> layout.transforms.add(
...    Transform(set_language))
>>> layout.parse().getroot().attrib["lang"]
'en'

再添加一个转换,将类分配给 <body>-标签。

>>> def set_class(node, value):
...     node.attrib["class"] = value
>>> layout.transforms.add(
...    Transform(lambda body: set_class(body, "front-page"), ".//body"))
>>> layout.parse().xpath('.//body')[0].attrib["class"]
'front-page'

项目详情


下载文件

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

源代码分发

z3c.layout-0.2.tar.gz (11.6 kB 查看散列)

上传时间

支持