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 的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | 0d7f1a71f2e92a71f2b02b77bf08eb69a1d1c5d28c3d7541f7f531310efa6e90 |
|
MD5 | 85a649bbabeb2dc165a531ca38a55661 |
|
BLAKE2b-256 | 88fdfc9361bf3add7e3eb3c4f56b42f52a41a0d260a5dd465f9a54f0697ed6ee |