Zope 产品
上个月,我们初步了解了开源 Zope 应用服务器。特别是,我们了解了如何使用 Zope 的 DTML(动态模板标记语言)标签来创建简单的动态站点,以及如何仅使用 Web 浏览器来管理网站。
但是,任何使用过 DTML 的人都知道,当您想要创建相对复杂的东西时,它就不再那么美好了。DTML 最适合少量使用或功能显而易见时使用;编写包含六个嵌套条件 (<dtml-if>) 标签的 DTML 页面很快就会变得难以阅读和维护,更不用说非常非模块化了。
另一个问题是 DTML 存在于各个文档内部,而不是在中心位置。如果我们想在多个地方重用功能,那么我们必须复制我们的 DTML 方法和文档。这意味着,当我们想要添加或更改某些功能时,我们必须遍历每个副本并对其进行修改。
解决此问题的方法是 Zope 产品。每个 Zope 产品实际上都是一个对象类(或一组类),可以在我们的网站中实例化任意次数。
本月,我们将了解 Zope 产品,它们构成了 Zope 灵活性的核心。在安装和使用一些现有产品后,我们将用 Python 编写我们自己的简单产品。
Zope 产品是一个代码、图形和 DTML 的包,它提供了一块可重用的功能。例如,如果我们有兴趣创建一个显示当前时间的简单页面,我们可以创建一个 DTML 文档
<p>It is now <dtml-var name="ZopeTime" fmt="fCommon">.</p>
但是,如果我们想扩展我们的页面,显示从另一个服务器通过 HTTP 检索的天气预报呢?DTML 不是这里的答案;即使我们可以使用它来创建我们的自定义功能,结果也将难以管理,并且写起来也很丑陋。由于 Zope 产品是用 Python 编写的,因此它们可以使用任何它们喜欢的 Python 模块,以 HTML 或任何其他兼容格式显示其输出。
由于每个产品都被视为一个单独的实体,因此即使它定义和使用多个类,我们也可以作为一个单元安装和删除它们。但是,这并不意味着每个产品都是独立的;相反,一个产品可以使用另一个产品提供的功能。
除了产品和 DTML 文档外,Zope 还提供了另外两种创建动态内容的方法:Python 脚本(由产品实现,不少于此)允许我们在 Zope 中编写和使用小型 Python 程序。我们还可以使用一个名为 ZClasses 的系统来创建、编辑和使用新产品。ZClasses 允许您仅使用 Web 浏览器和 DTML 来创建新产品(及其关联的类)。
虽然这四种选择提供了很大的灵活性,但对于初学者 Perl 程序员来说,决定使用哪一种有时可能很困难。Beehive 的 《Zope 之书》,我在本期Linux 杂志中对其进行了评论,建议在项目开始时使用 ZClasses,在每个人都同意设计后将代码迁移到成熟的产品。您的功能越复杂,您就越有可能想要使用或编写产品,而不是依赖 DTML 和 Python 脚本。
您可以通过 Zope 管理屏幕运行 Zope 产品的几乎每个方面,您可以通过 Zope 服务器的 /manage URL 访问该屏幕。单击左侧框架中的控制面板链接以调出 Zope 控制面板,然后单击主框架中的产品管理链接以调出产品管理屏幕。
您应该看到 Zope 产品列表,以及屏幕顶部标有“添加产品”的按钮。您可以通过 Web 修改的产品(包括我们上面简要提到的 ZClasses)用打开的框标识,而标准 Zope 产品具有闭合框图标。闭合框仅表示您无法通过 Web 修改产品本身。但是,大多数产品都允许您通过基于 Web 的界面设置一个或多个属性来自定义它们。但是,除非您修改源代码,否则产品本身保持不变。
每个产品实际上都是 Zope 安装目录下的 lib/python/Products 中的一个目录。Sessions 产品位于 lib/python/Products/Sessions 下,而 Transience 产品位于 lib/python/Products/Transience 中。(我在我的系统上将 Zope 安装在 /usr/local/zope/ 下,因此 Sessions 实际上位于 /usr/local/zope/lib/python/Products/Sessions/。)产品目录包含 Python 代码、文本文件和目录,包括
__init__.py:这是 Zope 在加载您的模块时扫描和执行的内容。其中,__init__.py 中的 initialize 方法调用 context.registerClass,它(顾名思义)告诉 Zope 您的产品存在,在 /manage 屏幕上的“添加”菜单中显示什么文本(使用 meta_type 参数),以及当按下“添加”按钮时如何创建您的产品的新实例(使用 constructors 参数)。
README.txt:顾名思义,这是特定产品的 README 文件。从控制面板中单击产品名称将显示一个 README 选项卡,以及其他选项卡。此选项卡允许您查看 README.txt,而无需查看文件系统。如果产品目录不包含名为 README.txt 的文件,则屏幕顶部不会出现 README 选项卡。
version.txt:此文件包含您的产品的名称和当前版本号,以减号 (-) 分隔。产品 Foo 的版本 1.2.3 因此将具有以下内容的 version.txt:Foo-1-2-3。此版本信息显示在控制面板中。
帮助文件:产品可能包含一个 help 目录,其中包含当您单击帮助链接时 Zope 显示的文本。帮助文件通常使用结构化文本编写,结构化文本是一种简约的格式化系统,在精神上类似于 Perl 的 POD 文档系统。结构化文本易于使用简单的文本编辑器编写,并且同样易于使用标准的 Linux 工具(如 less)阅读。
Zope 仅在启动时查看当前产品列表。这意味着,如果您安装了新产品,则需要重新启动 Zope 服务器。这可以从控制面板中最容易地完成。
现在我们已经了解了典型产品可能包含的内容,我们将通过从 Zope 网站下载产品,将其解压缩到 lib/python/Products 中并重新启动 Zope 来安装产品。如果一切顺利,我们新安装的产品应该会出现在我们的控制面板屏幕中。此外,我们将能够在我们的 Web 层次结构的任何位置创建此产品的新实例。
例如,让我们使用 Zope 的 Squishdot 产品创建一个 Slashdot 克隆。我们的首要任务是从 www.zope.org/Products 检索 Squishdot 的副本。Squishdot 列在“反馈”类别下,以及其他类别中,并且可能是最先列出的产品之一。单击指向 Squishdot 可下载版本的链接;截至撰写本文时,最新版本为 1.3.0。请注意,即使是中等复杂度的产品也相对较小;我下载的 Squishdot 版本略大于 256KB。
要安装 Squishdot,我们必须将其解压缩到 lib/python/Products 中。假设我们将新下载的文件放在 /downloads 中,这意味着我们可以按以下方式解压缩 Squishdot
# Set this to your Zope home export ZOPE=/usr/local/zope # Switch into the products directory cd $ZOPE/lib/python/Products # Unpack Squishdot into the current directory tar -zxvf /downloads/Squishdot-1-3-0.tar.gz
较旧的 Zope 产品希望从 Zope 根目录而不是从 lib/python/Products 中解压缩。不幸的是,似乎没有任何明显的方法可以知道产品是如何打包的,除非查看它
tar -ztvf /downloads/ProductName.tar.gz
如果每个文件名都以 lib/python/Products 路径名开头,那么您将需要在解压缩产品之前切换到 $ZOPE,而不是 $ZOPE/lib/python/Products。
解压缩存档是我们安装 Squishdot 所需要做的全部工作。但是,Zope 仅在启动时查找产品;我们必须重新启动服务器,然后才能在我们的系统上创建 Squishdot 的实例。最好的方法是从控制面板中单击“重新启动”按钮。如果您在单击“重新启动”后浏览器抱怨服务器不再运行,或者如果您在单击“重新启动”按钮后看到一个晦涩难懂的 Python 异常回溯,请不要惊慌。而是等待几秒钟,然后再次单击左侧框架中的控制面板链接,它应该可以工作。
您可以通过返回控制面板中的“产品管理”页面来检查您的产品是否已添加。如果新安装的产品(在本例中为 Squishdot)未出现在列表中,请仔细检查它是否已正确解压缩,以及权限是否允许 Zope 用户访问产品的文件。
此时,我们应该能够通过移动到 Zope 服务器的根 (/) 目录,从选择列表中选择 Squishdot 站点并单击“添加”来创建一个新的 Squishdot 站点。这将调用在 context.registerClass 中命名的 constructors 参数的方法,该方法由 Squishdot 的 __init__.py 中的 initialize 函数调用。
事实上,我们可以继续前进并在此时创建我们的 Squishdot 站点。但是 Squishdot 使用 Zope MailHost 对象(它代表 SMTP 服务器)发送电子邮件通知。如果您尚未创建和定义 MailHost,Squishdot 配置屏幕将提醒您这样做。
当 Squishdot 查找 MailHost 时,它会在当前目录中开始搜索。如果它找不到 MailHost 对象,则搜索将继续向上遍历目录树,当 Squishdot 到达 / 或找到 MailHost 对象时停止。虽然这可能看起来是一个简单的问题,但它演示了获取的概念,这对于 Zope 至关重要。此外,这意味着不同的 Squishdot 站点可以通过不同的 SMTP 服务器发送电子邮件,只需创建多个 MailHost 对象即可。实际上,我们可以在 / 中定义一个全局默认 MailHost,并在必要时通过在子目录中放置额外的 MailHost 对象来覆盖它。获取的概念渗透到 Zope 中,这意味着我们可以在本地级别定义或重新定义几乎任何内容——MailHost、用户、标头和样式表。
在这种特殊情况下,我们将在 / 目录中创建一个 MailHost 实例,方法是从新产品列表中选择 MailHost 并单击“添加”。由于 MailHost 对象代表 SMTP 服务器,因此此对象的配置非常简单,需要我们输入 Zope 服务器的 SMTP 服务器的名称。大多数 Linux 机器都运行自己的邮件服务器,因此 “localhost” 可能是一个合理的值。
强制性 ID 字段用于在当前目录中唯一标识此 MailHost,这就是 Zope 使用 ID 在 URL 中唯一标识对象的原因。正如文件名是目录中的唯一标识符一样,Zope 对象 ID 是文件夹或其他对象中的唯一标识符。可选的“标题”字段是为人类而不是为底层 Zope 服务器设计的;如果定义了标题,则对象的标题将从 Zope 服务器界面中显示。
创建 MailHost 对象后,您将返回到 / 的主 Zope 管理屏幕。您应该在对象列表中看到您的新 MailHost 对象(用小信封图标表示),以及您定义的任何标题。
我们现在准备好创建我们的 Squishdot 站点。使用右上角的选择列表和“添加”按钮添加新的 Squishdot 站点对象,选择 ID(即 URL 路径名)、可选标题和邮件主机,然后为您的 Squishdot 站点选择一些其他基本参数。例如,我选择了一个 atf 的 ID,否则将配置选项保留为默认值。
要进入我的 Squishdot 站点,我现在告诉我的 Web 浏览器显示 http://localhost:8080/atf/。Zope 收到对 /atf 的此请求,并看到我们正在引用一个 Squishdot 对象。然后 Zope 要求此对象显示自身。果然,我们看到了一个看起来有点像 Slashdot 但由 Zope 驱动的介绍性屏幕。
我们可以根据需要创建任意数量的 Squishdot 站点,请记住,每个新站点都必须有自己唯一的 ID。通过这种方式,我们可以为我们的组织自己的用途设置一个审核站点、一个非审核站点和另一个内部站点——每个站点都有自己的 URL,并且可能受到自己的一组用户和组的保护。
要修改 Squishdot 站点,只需将 /manage 附加到您要修改的对象的名称,如 http://localhost:8080/atf/manage。这会在我们的 Squishdot 站点上调用 Zope 的管理系统。使用屏幕顶部的选项卡,您可以修改几乎任何与 Squishdot 相关的参数,从审核规则到站点名称显示的文本颜色。
本月,我们讨论了 Zope 产品,并了解了如何在我们的系统上下载、安装和配置产品。虽然产品本质上比简单的 DTML 页面更复杂,但它们集中的代码和额外的灵活性使它们比 DTML 更适合严肃的任务。
下个月,我们将了解如何使用 Python 和 DTML 的组合编写我们自己的 Zope 产品。
电子邮件:reuven@lerner.co.il
Reuven M. Lerner 是一位专门从事 Web/数据库技术的顾问。他的著作《Core Perl》于 2002 年 1 月由 Prentice Hall 出版。他和他的妻子和女儿住在以色列的莫迪因。