页面、内容规则、组件和电子邮件的动态HTML生成和脚本编写
项目描述
简介
Easy Template (collective.easytemplate) 产品将简单的动态文本引入Plone。您不再需要只为几个动态页面创建完整的产品 - 最简单的事情可以直接从可视化编辑器中输入。
模板化是将简单的编程逻辑添加到文本输出的方式。此产品在Plone站点的各个部分添加或增强了对模板化的支持。
动机
Plone缺少为内容编辑器提供自定义、可扩展的模板化支持的内置支持。
用例
可能的用例包括:
在页面主体中使用未过滤的HTML(<script>等)
在页面上添加动态列表和表格,如新闻列表
在内容规则操作中添加动态的电子邮件正文、标题和接收者
在内容规则操作电子邮件中添加生成的内容
向登录用户和匿名用户显示不同的文本
动态创建简单的文本部件
示例
以下示例演示了在模板文档编辑模式下输入的文本如何转换为查看模式下的生成HTML片段。
您在Kupu中编写
Hello user! Please select one course from below: {{ list_folder("courses") }}
将产生以下输出
用户你好!
请从以下选项中选择一门课程
安装
添加到您的buildout
eggs = collective.easytemplate zcml = collective.easytemplate
运行Easy Template产品的附加产品安装程序。
collective.easytemplate依赖于collective.templateengines和Jinja2模板引擎。
安全通知
由于collective.easytemplate默认允许在页面上输入不安全的HTML,如<script>,因此其创建仅限于具有管理员角色的用户。
运行单元测试
必须安装Python eggs Cheetah、Jinja2和Products.LinguaPlone才能运行所有单元测试。
赞助
本产品的开发由London School of Marketing赞助。
关于模板引擎后端
默认情况下,使用Jinja 2模板引擎。有关语法,请参阅Jinja 2文档。这种语法非常简单的非XML语法,类似于Django模板。
简单的语法意味着对于基本用法,不需要HTML知识。您可以在HTML源代码和可视化编辑器视图中使用模板逻辑。
模板引擎可以在应用程序代码中切换。除了Jinja,Django和Cheetah引擎之外,collective.templateengines后端还支持collective.templateengines。
只有在Jinja引擎上,Zope安全功能才得到支持。其他模板引擎不提供兼容的沙盒。
模板元素
Easy Template产品使得以下位置可以使用模板。
文档
使用模板文档内容类型添加可脚本化的Plone页面。
此内容项有一个名为模板的标签页,允许您调整高级模板属性
显示错误:选择此选项后,错误消息将可供用户查看,无论他是管理员还是普通用户
未过滤的模板:用于输入原始HTML代码的字段。此代码不会被WYSIWYG编辑或HTML过滤功能混淆或过滤。
您可以通过将/testTemplate附加到对象URL来调试模板代码,查看直接模板引擎输出。它将返回纯文本视图,显示生成的模板消耗的内容。
字段和组件
collective.easytemplate.fields.TemplatedTextField 允许您在 Kupu 中编辑模板文档代码,模板以查看模式运行。它作为您自定义内容类型的 Archetypes 的 TextField() 的替代品。
部件
使用模板端口令牌来向您的端口令牌添加脚本。模板端口令牌基于 `
在可视化编辑器中输入模板代码。目前尚不支持原始 HTML 编辑。
端口令牌有 TALES 表达式 字段,用于确定端口令牌是否可见。这允许有条件地显示和隐藏端口令牌。
这对于特殊案例很有用,如
按语言显示端口令牌
仅对特定用户显示端口令牌
在特定时间内显示端口令牌
等等。
电子邮件
使用模板邮件操作来根据基于出站电子邮件消息的内容规则添加脚本。
模板扩展适用于所有字段: 收件人、主题 和 消息。您可以基于上下文对象动态查找接收者的电子邮件地址 - 它不需要是固定地址。
以下是一个高级示例,说明如何定义由工作流操作触发的模板出站电子邮件。
profiles/defaul/contentrules.xml
<?xml version="1.0"?> <contentrules> <rule name="email_local_coordinator_about_local_user_approval" title="Send email to LC when new LU needs approval" description="Send email to local coordinators that management has approved new member to their center and local coordinator actions are needed" enabled="True" event="Products.CMFCore.interfaces.IActionSucceededEvent" stop-after="False"> <conditions> <condition type="plone.conditions.WorkflowTransition"> <property name="wf_transitions"> <element>my_workflow_transition_id_here</element> </property> </condition> </conditions> <actions> <action type="collective.easytemplate.actions.Mail"> <property name="source">{{ portal.getProperty('email_from_address') }}</property> <property name="message"> New local user {{ title }} needs approval. Please approve local user at {{ context.absolute_url() }} </property> <property name="recipients">{{ context.getTheReceiverEmailAddressFromTheContextSomehow() }}</property> <property name="subject">New local user {{ title }} needs approval</property> </action> </actions> </rule> <assignment location="/" name="email_local_coordinator_about_local_user_approval" enabled="True" bubbles="True" /> </contentrules>
然后是用于测试此功能的示例单元测试代码
from zope.component import getUtility, getMultiAdapter, getSiteManager from Products.MailHost.interfaces import IMailHost from Products.SecureMailHost.SecureMailHost import SecureMailHost class DummySecureMailHost(SecureMailHost): meta_type = 'Dummy secure Mail Host' def __init__(self, id): self.id = id self.sent = [] self.mto = None def _send(self, mfrom, mto, messageText, debug=False): self.sent.append(messageText) self.mto = mto ... class BaseTestCase: """We use this base class for all the tests in this package. If necessary, we can put common utility or setup code in here. Mix-in class, also include FunctionalTestCase or PloneTestCase. """ def afterSetUp(self): ... self.loginAsPortalOwner() sm = getSiteManager(self.portal) sm.unregisterUtility(provided=IMailHost) self.dummyMailHost = DummySecureMailHost('dMailhost') sm.manage_changeProperties({'email_from_address': 'moo@isthemasteofuniverse.com'}) sm.registerUtility(self.dummyMailHost, IMailHost) ... def test_my_email_on_workflow_transition(self): self.workflow = self.portal.portal_workflow self.portal.invokeFactory("MyContentType", "myobject") myobject = self.portal.myobject self.dummyMailHost.sent = [] self.workflow.doActionFor(myobject, "my_workflow_transition_id_here") review_state = self.workflow.getInfoFor(myobject, 'review_state') self.assertEqual(review_state, "my_new_workflow_state") # Check that the email has been send self.assertEqual(len(self.dummyMailHost.sent), 1) # Outgoing emails increased by one self.assertEqual(self.dummyMailHost.mto, ["receiver@dummy.host"]) ...
安全
默认情况下,模板函数受限于当前用户的权限 - 这意味着输出可能会根据您登录的用户而有所不同。用户不应能够绕过 Zope 沙盒。
然而,一些标签并不完全安全(逃脱查看权限)并且您可能希望在多用户生产网站上禁用它们。
本产品不保证安全性。对于具有高安全要求站点,请咨询作者。
安全单元测试可在 此处 找到。
模板上下文
模板上下文包含您在模板中可用的顶级变量。
变量在 context/plone.py 源代码文件中定义。
上下文变量
Plone 使用称为 Archetypes 的子系统来定义内容类型。内容类型是由模式中定义的字段构建的。所有默认的 Plone 内容类型(文档、文件夹、事件、新闻等)都是基于 Archetypes 的。
基于 Archetypes 的对象以 “原样” 暴露给模板引擎的 上下文 变量。其他上下文变量函数由运行对象的 Python 类定义。
您可以通过调用 getXXX 访问器函数来查询单个字段的值。公开的字段在 Archetypes 对象的模式源代码中定义。
以下是一些示例。
打印内容标题
{{ context.Title().decode("utf-8") }}
打印文档正文文本(HTML)
{{ context.getBody() }}
获取当前对象的 URL
{{ context.absolute_url() }}
如果您对该对象具有写访问权限,您甚至可以在模板中设置值,尽管这并不很有用
{{ context.setTitle('Moo the novel') }}
Unicode和UTF-8
Jinja,就像 Python 2.x 软件一样,假设所有字符串都是 ASCII 或 Unicode。
如果您正在输出文本,它
包含国际字符
已知为 UTF-8
您必须在模板中解码输入文本。对于 Plone,以下内容已知为 UTF-8
所有 Archetypes 文本字段访问器,如 Title()、Description(),都返回 UTF-8 字节字符串
portal_catalog 条目,如 Title、Description,直接反映 Archetypes 值并包含 UTF-8 字节字符串
对于其他字符串,请查阅 Plone 源代码
要输出此类文本,必须执行解码。您可以通过直接调用 Python 字节码字符串的 decode() 方法来完成此操作。
对于类似访问器的函数
{{ context.Title().decode("utf-8") }}
对于目录大脑数据
{{ brain.Title.decode("utf-8") }}
否则,当遇到国际字符时,您将看到类似这样的内容
Traceback (innermost last): Module collective.templateengines.utils, line 104, in wrapExceptions Module collective.templateengines.backends.jinja, line 104, in applier Module jinja2.environment, line 705, in render Module <template>, line 3, in top-level template code UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 1: ordinal not in range(128)
遍历
遍历是一种在 Zope 的对象图中查找对象的方法。
要访问除当前模板文档之外的其他对象,您可以使用 Zope 的遍历机制在文件夹层次结构中进行遍历。
获取父文件夹
{{ context.aq_parent }}
可以使用对象 ID 遍历文件夹内容对象。
获取当前文件夹中 URL ID 为 'sister' 的姐妹页面
{{ context.aq_parent.sister }}
门户
门户是您站点的根 Plone 对象。您可以使用它作为遍历起点来查询您站点的其他对象。例如:
一些可用的方法在 IPortal 接口中有描述。
要访问顶级新闻文件夹
{{ portal.news }}
门户状态
portal_state 存储有关系统当前状态的信息。例如,用户是否登录,导航基础,门户标题,活动语言等。
该对象实现了 IPortalState 接口。
如何为匿名用户和登录用户分别输出示例
{% if portal_state.anonymous() %} anon {% else %} logged in {% endif %}
用户
用户变量持有当前用户安全信息。
这实现了 Basic user 接口。
最有用的功能是通过 getUserName() 获取当前用户名。
成员
用户成员信息。此信息取决于使用的成员后端(Plone 默认,LDAP,SQL,自定义等)。
门户URL
当调用时,portal_url 返回当前门户根 URL。
示例
<a href="{{ portal_url() }}">Home</a>
高级示例
新闻和博客表
以下片段将创建一个两列的表格。左列包含摘要和链接到网站上所有已发布的新闻。右列包含从RSS源获取的外部博客条目的链接。新闻查询是语言敏感的 - 只显示当前活动语言中的新闻。
两列都限制为三个条目。
文本已翻译,并且当默认Plone翻译目录缺少合适的msgids时,使用自定义翻译目录twinapex。
此示例必须放入未过滤的模板输入框中,因为Kupu似乎在代码中插入了不需要的 字符。
示例
<table class="front-page two-column"> <tbody> <tr> <td class="column-2"> <h2> <a href="{{ portal_url() }}/news"> {{ translate("news", "twinapex") }} </a> </h2> {% for item in query({"portal_type":"News Item", "review_state" : "published", "sort_on":"Date", "sort_order":"reverse", "sort_limit":3}) %} <div class="fp-item"> <a href="{{ item.getURL() }}">{{ item.Title }}</a> <p> {{ item.Description }} </p> <p class="timestamp">{{ item.Date }}</p> </div> {% endfor %} <p class="more"> <a class="more" href="{{ portal_url() }}/news"> {{ translate("box_more_news_link", default="More news...") }} </a> </p> </td> <td class="column-2"> <h2> <a href="{{ portal_url() }}/news"> {{ translate("blog", "twinapex") }} </a> </h2> {% for item in rss_feed("http://blog.redinnovation.com/feed/")[0:3] %} <div class="fp-item"> <a href="{{ item.url }}">{{ item.title }}</a> <p class="timestamp">{{ item.friendly_date }}</p> </div> {% endfor %} <p class="more"> <a class="more" href="http://blog.twinapex.fi"> {{ translate("box_morelink", default="More...") }} </a> </p> </td> </tr> </tbody> </table>
调试技巧
如果模板编译失败,您可能已经犯了复制粘贴错误。请以原始HTML模式查看模板以跟踪错误
模板表达式中的HTML标签
模板表达式中的硬换行符
项目详情
下载文件
下载适用于您的平台的文件。如果您不确定该选择哪个,请了解更多关于安装包的信息。
源代码分发
collective.easytemplate-0.8.0.zip的散列值
算法 | 散列摘要 | |
---|---|---|
SHA256 | 7a0c630afa600ba1d8081e5d989e05060c051e059dbea9ce81ca2d8b69b5c8b3 |
|
MD5 | d052b43c160bcdfb295d6e21cffbb0b9 |
|
BLAKE2b-256 | 7a39977667e5095629090b9c44b89907111dd49500e7c819e9c35da475f13cfd |