Bricolage 模板
在过去的几个月中,我们了解了 Bricolage,这是一个基于 PostgreSQL、mod_perl 和 Apache 的开源内容管理系统 (CMS)。Bricolage 在过去几年中获得了相当大的关注,部分原因是其开源许可证,部分原因是其所基于的开源技术,部分原因是其功能集与许多专有 CMS 软件包相当,更不用说开源 CMS 产品了。
本月,我们将通过了解 Bricolage 对模板的使用来结束我们的 Bricolage 之旅。到目前为止,我们已经了解了 Bricolage 提供的大量管理和编辑功能,但只有当您可以自定义其输出并使生成的网站具有吸引力时,CMS 才是有用的。
HTML 模板已经存在很长时间了,它们是在静态页面和将 HTML 放入程序中之间的一个很好的折衷方案,这使得设计人员无法访问它。如果您希望 HTML 页面动态变化,使用模板是一个不错的选择。
当然,这也提出了一个重要的问题:您应该使用哪种模板?存在数百种不同的模板系统,其中包括几十种用 Perl 编写的。其中一些,例如 Text::Template,本身不是 HTML 模板系统,但它们已在各种 Web 相关任务中成功使用。
您应该使用哪种模板系统是一个争论,其激烈程度仅次于 Linux/BSD 和 Emacs/vi 的讨论。幸运的是,Bricolage 超越了这场争论,与 HTML::Mason 和 Template Toolkit 都愉快地共存。理论上可以使用另一个模板系统,但这两种系统都非常流行和强大,足以满足许多 Bricolage 用户。我个人更喜欢 HTML::Mason,并使用 Mason 演示 Bricolage 模板,但如果您是 Template Toolkit 的粉丝,请随意使用它。
模板是 HTML 页面内容的通用轮廓。一切都被认为是静态的,除了变量,变量的值在运行时被填充(在程序员的语言中称为插值)。例如,考虑以下模板
<html> <head> <title><% $title %></title> </head> <body> <h1><% $headline %></h1> <p><% $body_text %></p> </body> </html>
上面的模板使用 Mason 语法编写,始终具有标题、头条新闻和段落。但是,标题、头条新闻和正文文本的内容是可变的。
Mason 还提供了两个全局变量:$r,标准的 mod_perl 对象,它使我们能够通过其 Perl API 访问 Apache 服务器的内部结构;以及 $m,该对象提供有关整体 Mason 环境和当前特定 Mason 模板的更多信息。
Bricolage 在此组合中引入了三个新对象。最重要的是 $story,它包含有关当前故事的信息。故事包含元素,元素本身可以包含其他元素;当前元素可以使用对象 $element 获取。最后,Bricolage 使用称为“刻录器 (burner)”的机制将页面发送到输出通道(通常但不一定是指网站)。
在我们继续之前,了解 Mason 的自动处理程序 (autohandlers) 也很重要,它可以使站点具有统一的外观和感觉。如果特定目录存在自动处理程序,则始终会调用自动处理程序,而不是该目录中的文件。也就是说,如果您请求 /abc/def.html 并且 /abc/autohandler 已经存在,则会调用 /abc/autohandler 而不是 /abc/def.html。这乍一看可能很奇怪,而且确实如此——除非自动处理程序可以通过调用 $m->call_next() 在任何时候调用最初请求的模板。
一个常见的策略是将尽可能多的公共材料放在自动处理程序内部,包括菜单、图像和头条新闻。自动处理程序是一个 Mason 模板,与其他模板一样,只是调用方式不同。在自动处理程序内部,在各种头条新闻、图像和菜单之间,您插入对 $m->call_next() 的调用,这将插入请求的页面。因此,您获得了使用多个模板进行模块化设计的好处,同时还能够通过更改单个文件来重新设计站点。
自动处理程序是嵌套的,这意味着 Mason 会调用它在其所有父目录中可以找到的所有自动处理程序。因此,如果我们请求 /abc/def.html,Mason 首先查找并调用 /autohandler,然后是 /abc/autohandler,最后是 /abc/def.html。这允许您创建特定于部分的外观和感觉,以及基于部分的菜单和其他信息。
我假设您已经在您的系统上创建并发布了至少一个故事。如果您不确定如何创建和发布故事,请参阅我之前在过去几期中关于 Bricolage 的文章。一旦您发布了一个故事,它就会被发送到特定的输出通道,可以通过复制文件系统上的文件或使用 FTP 将其移动到远程服务器。
故事的外观和感觉由模板决定。因此,在我们创建我们自己的简单模板之前,让我们看看系统附带的基本示例。转到 Bricolage 管理员屏幕左侧模板菜单中的“查找模板”链接(用户名是 administrator,密码是 change me now!),然后单击“搜索”按钮,无需在文本字段中输入任何内容。您应该看到一个模板列表,系统中每种元素类型对应一个模板(图 1)。
在许多方面,Bricolage 模板就像故事:它们在不同的工作台创建、编辑和部署;对它们的访问仅限于某些用户和组;Bricolage 使用简单的版本控制系统跟踪更改(并避免冲突)。实际上,如果您查看图 1,您可以看到每个模板都有一个与之关联的版本号。可以通过单击相关的复选框,然后单击页面底部的“签出”按钮,将每个模板从版本控制系统中签出。签出的模板可以从“模板”菜单下的“活动模板”链接中获得。
在 Bricolage 中,故事只是可发布的元素类型之一。此外,每个元素可以包含任意数量的其他元素。Bricolage 附带了几个预定义的顶级元素,例如故事、书评和专栏,以及几个旨在包含在其他元素中的其他元素,例如引述。
如果您考虑一份日报,您应该意识到即使对于相似的元素,每个部分的样式也不同。《纽约时报》都市版面的专栏看起来与商业版面的专栏不同,商业版面的专栏看起来又与社论版面的专栏不同。也就是说,它们都是专栏。Bricolage 通过允许您为元素分配类别来解决这个问题。因此,如果您正在为体育版面撰写专栏,您可以指示它是体育类别的一部分。当 Bricolage 将专栏发布到 Web 上时,它会查找 /sports/column.mc 模板。如果存在,Bricolage 将应用该特定模板。如果不存在,Bricolage 将在顶部(根)类别中查找 column.mc 模板。换句话说,如果您有一个元素的顶级模板,它将充当系统上该类型的所有元素的后备或默认值。您可以通过定义特定于类别的模板,为站点的某些或所有部分提供不同的外观和感觉。
正如您从图 2 中看到的,我已经签出了 /story.mc 模板,它是故事的顶级模板。我没有视图链接,而是有一个编辑链接,允许我修改模板。我也可以通过转到活动模板页面来编辑模板,该页面为我提供了类似的编辑链接。打开模板进行编辑,您应该会看到类似于图 2 的屏幕。
编辑模板类似于编辑故事或任何其他元素类型,只是您正在修改故事将插入其中的容器。如果您只插入静态 HTML,则每个元素看起来都相同。因此,诀窍是使用预定义的 $story、$element 和 $burner 对象来用动态内容填充页面。例如,这是默认的 /story.mc 模板
<!-- Start "Story" --> %# Only show this if we are on the first page % unless ($burner->get_page ) { <h1><% $story->get_title %></h1> <% $element->get_data('deck') %> <hr /> % } %# Display all the pages of this story % $burner->display_pages('page'); <br> Page <% $burner->get_page + 1 %> <!-- End "Story" -->
正如您所看到的,上面的模板相当简单。实际站点可能会插入首字下沉、在 CSS 中设置一些样式或包含一些其他静态文本来标识站点。基本版本的 /story.mc 执行以下操作
它从 $burner->get_page() 获取当前页码。页码从 0 开始;但是,如果我们在第一页,我们会显示故事的标题和元素的副标题。标题来自 $story 对象,使用 $story->get_title(),副标题(摘要)来自元素本身。请注意 $element->get_data() 是一个相当通用的方法;我们可以使用 $element->it 从元素中检索任何字段。
我们通过从刻录器请求故事来显示故事,使用 $burner->display_pages('page')。
最后,我们再次使用 $burner->get_page() 在页面底部显示页码。
如果我们删除页码并在模板的顶部或底部插入一些我们自己的静态 HTML 会发生什么?然后,我们的更改会反映在系统上的所有故事中。但重要的是要记住,并非所有元素都是故事,因此我们对 /story.mc 所做的更改不会影响专栏、书评或其他元素类型。
当您完成编辑 /story.mc 后,您可以单击页面底部的“签入”按钮。当您签入模板时,您可以将其发送到开发模板工作台(默认值),也可以立即部署它。如果您发现影响整个站点的模板错误,此选项特别有用;您可以修改模板,部署它并立即查看结果。
最后,请注意 /story.mc 如何不包含任何 <html> 或 <title> 标签。这是因为这些项目在自动处理程序中实现。默认情况下,/autohandler 模板(您可以从“模板”菜单中查看、签出和编辑它)定义如下
<!-- Start "autohandler" --> <html> <head> <title><% $story->get_title %></title> </head> <body> % $burner->chain_next; </body> </html> <!-- End "autohandler" -->
自动处理程序是整个站点全局的,它将故事的标题放在适当的 HTML <title> 标签中。它还通过调用 $burner->chain_next() 将适当的页面内容合并到模板中。
如果您想包含全局 CSS 样式表,在每个页面的顶部添加标准菜单,或在站点上每个页面的顶部放置公司的徽标,则此自动处理程序是执行此操作的位置。并且由于自动处理程序是嵌套的,因此您可以为整个站点设置全局自动处理程序,并在每个类别中设置特定于部分的自动处理程序。
到目前为止,我们只查看了现有模板。但是,创建新模板非常容易。只需转到“模板”菜单,然后单击“新建模板”。您应该看到一个如图 3 所示的屏幕,要求您指示模板应应用的输出通道和类别。单击“下一步”,系统会要求您输入模板应应用的元素类型。
类别-通道-元素组合必须是唯一的。因此,您可以为输出通道、类别或特定元素设置多个模板。但是对于根 (/) 类别中 Web 输出通道中的故事元素,只能有一个模板。如果您尝试违反此唯一性约束,Bricolage 会发出警告,告诉您该组合已经存在模板。对此问题有几种解决方案;一种是创建新的元素类型,另一种是创建新的类别,还有一种是修改该组合的现有模板。最佳行动方案取决于您的具体目标。
我将为豆腐类别中的专栏创建一个新模板,在 Bricolage 中表示为 /tofu/column.mc。一旦我单击“创建”按钮,我就会看到一个编辑屏幕,允许我创建或修改我的模板。我将使我的模板非常简单
<!-- Start "tofu/column" --> %# Display this story % $burner->display_pages('page'); <!-- End "tofu/column" -->
请注意我们如何在定义周围放置 HTML 注释。这使得在将模板转换为 HTML 并发送到用户的浏览器时更容易调试模板。我可以根据个人经验向您保证,Mason 模板的嵌套性质,尤其是具有多个自动处理程序时,可能会令人抓狂。
一旦我从“签入”菜单中选择并部署,然后单击“签入”按钮,我的模板就会被部署。现在,任何类别为豆腐的专栏都将使用此模板而不是更通用的全局专栏模板进行格式化。
当然,如果我想返回并编辑我的模板,我可以按照我们之前看到的方式进行——找到它,签出并编辑它。
Bricolage 像任何严肃的 CMS 一样,通过使用模板可以轻松创建统一的外观和感觉。由于 Bricolage 基于标准的开源工具,例如 mod_perl 和 Apache,因此它可以利用 mod_perl 的现有模板系统,包括 HTML::Mason 和 Template Toolkit。本月,我们了解了如何创建和修改与各种元素类型和类别关联的模板,从而为我们提供了概括站点外观和感觉所需的灵活性,而不会受到约束。
资源
关于 Bricolage 的主要信息来源是该项目的网站 bricolage.cc。该站点有指向可下载源代码(托管在 SourceForge 上)、文档和 Bugzilla 实例 (bugzilla.bricolage.cc) 的指针,用于错误报告和功能请求。
SourceForge 托管了几个 Bricolage 邮件列表,开发人员积极参与其中。如果您有疑问或想了解新版本,您可以从 SourceForge 页面订阅 sourceforge.net/projects/bricolage。
Bricolage 文档通常非常好,但技术性较强。O'Reilly and Associates 出版了更用户级别的系统介绍,作为他们最近出版的关于 Mason 的书的附录。您可以在线阅读该附录,网址为 www.masonbook.com/book/appendix-d.mhtml。
您可以从 Mason 图书站点 www.masonbook.com 和 Mason 主页 www.masonhq.com 了解有关 Mason 的更多信息。
最后,您可以在 david.wheeler.net 上了解有关 David Wheeler(Bricolage 的主要作者和维护者)的更多信息,并在 www.kineticode.com 上了解有关他的公司 Kineticode 的更多信息。
Reuven M. Lerner,一位长期的 Web/数据库编程顾问,现在是伊利诺伊州埃文斯顿西北大学学习科学的研究生。您可以通过 reuven@lerner.co.il 与他联系。