为Grok提供的Chameleon页面模板支持
项目描述
grokcore.chameleon
grokcore.chameleon 使得在 Grok 中使用 Chameleon 页面模板成为可能。有关 Grok 和 Chameleon 页面模板的更多信息,请参见
安装
请注意,grok 的未来版本将自身依赖于 grokcore.chameleon 并对其进行配置。换句话说,基于 chameleon 的模板将从该版本开始默认可用!
要使用 Grok 与 Chameleon 页面模板,您只需将 grokcore.chameleon 作为 egg 安装,并包含其 ZCML。最佳做法是将 grokcore.chameleon 作为您的应用程序的依赖项,通过将其添加到 setup.cfg 中的 install_requires 列表中来实现。如果您使用 grokproject 创建了应用程序,setup.py 位于项目根目录。它看起来可能像这样
install_requires=['setuptools', 'grokcore.chameleon', # Add extra requirements here ],
请注意,如果您的项目 buildout.cfg 中使用 allow-picked-versions = false 指令,您必须将几个软件包的版本号指定添加到 [versions] 部分。
然后,在 configure.zcml 中包含 grokcore.chameleon。如果您使用 grokproject 创建了应用程序,它位于 src/<projectname>/configure.zcml。在包含 grok 的 include 行之后、当前包的 grokking 之前添加 include 行。它看起来可能像这样
<include package="grok" /> <include package="grokcore.chameleon" /> <grok:grok package="." />
如果您在 configure.zcml 中使用 autoInclude,则不需要执行此后续步骤。
然后再次运行 bin/buildout。现在您应该看到 buildout 输出如下(版本号可能不同)
Getting distribution for 'grokcore.chameleon'. Got grokcore.chameleon 0.5.
这就完成了。您现在可以在 Grok 应用程序中开始使用 Chameleon 页面模板。
使用方法
grokcore.chameleon 支持 Grok 标准的模板放置在模板目录中,例如 app_templates,因此您可以通过将 Chameleon 页面模板放置在模板目录中,像使用常规 ZPT 模板一样,来使用 Chameleon 页面模板。
尽管 chameleon 模板本身没有模板文件扩展名的标准,但 Grok 需要在文件扩展名和模板语言实现之间建立关联,以便知道使用哪个实现。
grokcore.chameleon 声明使用扩展名 *.cpt(Chameleon page template)用于 Chameleon 页面模板。
您还可以内联使用 Chameleon 页面模板。其语法如下
from grokcore.chameleon.components import ChameleonPageTemplate index = ChameleonPageTemplate('<html>the html code</html>')
或如果您使用文件
from grokcore.chameleon.components import ChameleonPageTemplateFile index = ChameleonPageTemplateFile(filename='thefilename.html')
详细描述
Grok 支持 Chameleon 驱动的模板。
使用 grokcore.chameleon,您可以使用由 Chameleon 解析和渲染的模板,并使用 Zope 页面模板模板语言。
Chameleon Zope 页面模板
Chameleon支持Zope页面模板,可以使用.grok编写模板,文件扩展名为.cpt(=Chameleon页面模板)。
Chameleon页面模板在几个方面与标准Zope页面模板不同,最值得注意的是
默认情况下,表达式以Python模式解析。这意味着,您必须使用tal:content="view.value",而不是tal:content="view/value"。现在,所有以python:开始的TAL表达式现在可以通过跳过此标记来缩短。
此外,还支持Genshi风格的变量替换。例如,您可以编写${myvar}而不是tal:content="myvar"。
除此之外,大多数常规Zope页面模板的规则也适用于Chameleon页面模板。
有关更多信息,请参阅Chameleon页面。
先决条件
在我们能够看到模板在行动之前,我们需要正确注册并设置一些使用的变量
>>> import os >>> testdir = os.path.join(os.path.dirname(__file__), 'tests') >>> cpt_fixture = os.path.join(testdir, 'cpt_fixture') >>> template_dir = os.path.join(cpt_fixture, 'app_templates')
我们注册一切。在我们可以grok我们的 fixture之前,我们必须grok grokcore.chameleon 包。这样,新的模板类型就被注册到框架中
>>> import grokcore.view >>> grokcore.view.testing.grok('grokcore.chameleon') >>> grokcore.view.testing.grok('grokcore.chameleon.tests.cpt_fixture')
我们创建一个巨兽,它应该提供许多由Chameleon页面模板驱动的视图,并将其放入数据库以设置位置信息
>>> from grokcore.chameleon.tests.cpt_fixture.app import Mammoth >>> manfred = Mammoth() >>> getRootFolder()['manfred'] = manfred
此外,我们为获取关于manfred的不同视图做准备
>>> from zope.publisher.browser import TestRequest >>> from zope.component import getMultiAdapter >>> request = TestRequest()
简单模板
我们准备了一个简单的洞穴壁画视图。模板看起来像这样
>>> cavepainting_cpt = os.path.join(template_dir, 'cavepainting.cpt') >>> with open(cavepainting_cpt, 'r') as f: ... print(f.read()) <html> <body> A cave painting. </body> </html>
渲染后的视图看起来像这样
>>> view = getMultiAdapter((manfred, request), ... name='cavepainting') >>> print(view()) <html> <body> A cave painting. </body> </html>
变量替换
模板可以访问如view、context、static以及其方法和属性。food视图正是如此。模板看起来像这样
>>> food_cpt = os.path.join(template_dir, 'food.cpt') >>> with open(food_cpt, 'r') as f: ... print(f.read()) <html> <body> <span tal:define="foo 'a FOO'"> ${view.me_do()} <span tal:replace="structure view.me_do()" /> CSS-URL: ${path:static/test.css} My context is: ${view.url(context)} ${foo} <span tal:replace="foo" /> </span> </body> </html>
渲染后的视图看起来像这样
>>> view = getMultiAdapter((manfred, request), name='food') >>> print(view()) <html> <body> <span> <ME GROK EAT MAMMOTH!> <ME GROK EAT MAMMOTH!> CSS-URL: dummy:/test.css My context is: http://127.0.0.1/manfred a FOO a FOO </span> </body> </html>
正如我们所看到的,Genshi-like替换和TAL-like替换之间存在差异:虽然这两个表达式
${view.me_do()}
和
<span tal:replace="view.me_do()" />
实际上渲染了相同的字符串 ,后者为 。<ME GROK EAT MAMMOTH!>
<ME GROK EAT MAMMOTH!>
支持的变量
每个模板至少提供以下变量
- template
模板实例
- view
关联视图
- context
视图上下文
- request
当前请求
正如我们所看到的,当我们查看我们的fixture中的vars.cpt
>>> cpt_file = os.path.join(template_dir, 'vars.cpt') >>> with open(cpt_file, 'r') as f: ... print(f.read()) <html> <body> This template knows about the following vars: <BLANKLINE> template (the template instance): ${template} <BLANKLINE> view (the associated view): ${view} <BLANKLINE> context (the context of the view): ${context} <BLANKLINE> request (the current request): ${request} </body> </html>
并渲染它
>>> view = getMultiAdapter((manfred, request), name='vars') >>> print(view()) <html> <body> This template knows about the following vars: <BLANKLINE> template (the template instance): <PageTemplateFile ...vars.cpt> <BLANKLINE> view (the associated view): <grokcore.chameleon.tests.cpt_fixture.app.Vars object at 0x...> <BLANKLINE> context (the context of the view): <grokcore.chameleon.tests.cpt_fixture.app.Mammoth object at 0x...> <BLANKLINE> request (the current request): CONTENT_LENGTH: 0 GATEWAY_INTERFACE: TestFooInterface/1.0 HTTP_HOST: 127.0.0.1 SERVER_URL: http://127.0.0.1 </body> </html>
支持自定义模板命名空间名称
>>> view = getMultiAdapter((manfred, request), name='namespace') >>> print(view()) <html> <body> This template knows about the following custom namespace name: <BLANKLINE> myname: Henk <BLANKLINE> </body> </html>
内联模板
我们还可以定义内联模板。在我们的app.py中,我们定义了一个内联模板,如下所示
from grokcore.chameleon import components ... class Inline(grokcore.view.View): sometext = 'Some Text' inline = components.ChameleonPageTemplate( "<html><body>ME GROK HAS INLINES! ${view.sometext}</body></html>")
如果我们渲染这个视图,我们会得到
>>> view = getMultiAdapter((manfred, request), name='inline') >>> print(view()) <html><body>ME GROK HAS INLINES! Some Text</body></html>
TAL 表达式
从grokcore.chameleon 0.5版本开始,我们部署了全功能的Chameleon包。
模板中支持的TAL/TALES表达式取决于安装的Chameleon版本,而我们支持一些额外的,与Zope相关的TALES表达式。
所有支持的表达式和语句的列表可以在chameleon.zpt文档中找到。由grokcore.chameleon提供的额外TALES表达式包括
- exists
告诉模板命名空间中是否存在名称。
- not
将表达式评估为布尔值并取反。
- path
将表达式作为路径处理,而不是Python表达式。
- provider
支持视图提供者。
在我们的 app.py 中,我们定义了一个特殊的视图来显示一些特殊表达式。这还包括一个视图组件
import grok from grokcore.chameleon import components class Mammoth(grok.Application, grok.Container): pass ... class Expressions(grok.View): pass class MainArea(grok.ViewletManager): grok.name('main') class MainContent(grok.Viewlet): grok.view(Expressions) grok.viewletmanager(MainArea) def render(self): return 'Hello from viewlet'
现在我们可以在我们的 fixture 的 expressions.cpt 模板中使用 TALES 表达式 not:、path:、exists: 和 provider:
>>> cpt_file = os.path.join(template_dir, 'expressions.cpt') >>> with open(cpt_file, 'r') as f: ... print(f.read()) <html> <body> <div tal:define="food 'Yummy Dinoburger'" tal:omit-tag=""> <!-- We support `exists` --> <div tal:condition="exists: food"> ${food} </div> <BLANKLINE> <!-- We support `not` --> <div tal:content="not: food" /> <div tal:content="not('food')" /> <div tal:content="not: 1 in [2,3]" /> <div tal:content="not: not: food" /> <BLANKLINE> <!-- We support `path` --> <div tal:content="path: food/upper" /> <BLANKLINE> <!-- We support `provider` --> <tal:main content="structure provider:main" /> <BLANKLINE> </div> </body> </html>
并渲染它
>>> view = getMultiAdapter((manfred, request), name='expressions') >>> print(view()) <html> <body> <BLANKLINE> <!-- We support `exists` --> <div> Yummy Dinoburger </div> <BLANKLINE> <!-- We support `not` --> <div>False</div> <div>False</div> <div>True</div> <div>True</div> <BLANKLINE> <!-- We support `path` --> <div>YUMMY DINOBURGER</div> <BLANKLINE> <!-- We support `provider` --> Hello from viewlet <BLANKLINE> <BLANKLINE> </body> </html>
翻译
>>> # Monkeypatch zope.i18n.negotiate >>> import zope.i18n >>> import zope.i18n.config >>> print(getMultiAdapter((manfred, request), name='menu')()) <html> <body> <h1>Menu</h1> <ol> <li>Deepfried breaded veal cutlets</li> </ol> </body> </html>>>> # What's for food today in Germany? >>> # We need to monkey patch the language settings for this test. >>> old_1, old_2 = zope.i18n.negotiate, zope.i18n.config.ALLOWED_LANGUAGES >>> zope.i18n.negotiate = lambda context: 'de' >>> zope.i18n.config.ALLOWED_LANGUAGES = ['de'] >>> print(getMultiAdapter((manfred, request), name='menu')()) <html> <body> <h1>Menu</h1> <ol> <li>Schnitzel</li> </ol> </body> </html>>>> # Restore the monkey patch. >>> zope.i18n.negotiate, zope.i18n.config.ALLOWED_LANGUAGES = old_1, old_2
宏
使用 grokcore.chameleon,我们还可以使用宏,尽管它和常规的 Zope 页面模板略有不同。
我们可以这样定义宏
>>> cpt_file = os.path.join(template_dir, 'macromaster.cpt') >>> with open(cpt_file, 'r') as f: ... print(f.read()) <p xmlns:metal="http://xml.zope.org/namespaces/metal" metal:define-macro="hello"> Hello from <b metal:define-slot="name">macro master</b> </p>
定义的宏 hello 可以在另一个 Chameleon 模板中使用,具有 METAL 属性 use-macro。
要引用本地宏,即在同一模板中定义的宏,可以使用类似以下的方式
<div metal:use-macro="template.macros['<macro-name>']"> Replaced by macro </div>
其中 <macro-name> 必须是一个现有的宏名称。
要引用外部模板中的宏,必须使用 path: 表达式,如下所示
<div metal:use-macro="path: context/@@<viewname>/template/macros/<macro-name>"> Replaced by external macro </div>
其中 <viewname> 指的是在 context 上存在的视图,而 macro- name 再次指在指定模板中存在的宏。
注意,这与在标准 Zope 页面模板中引用宏的方式不同。简写 view/macros/<macro-name> 只适用于常规 Zope 页面模板。
以下模板同时使用了这两种方法
>>> cpt_file = os.path.join(template_dir, 'macrouser.cpt') >>> with open(cpt_file, 'r') as f: ... print(f.read()) <html xmlns:metal="http://xml.zope.org/namespaces/metal"> <body> <p metal:define-macro="hello"> Hi there from macro user! </p> <div metal:use-macro="template.macros['hello']"> Fill this </div> <BLANKLINE> <div metal:use-macro="path: context/@@macromaster/template/macros/hello"> <b metal:fill-slot="name">user slot</b> Fill this too </div> </body> </html>
在渲染时,主模板中定义的槽位也由宏用户内容填充
>>> cpt_file = os.path.join(template_dir, 'macrouser.cpt') >>> view = getMultiAdapter((manfred, request), name='macrouser') >>> print(view()) <html> <body> <p> Hi there from macro user! </p> <p> Hi there from macro user! </p> <BLANKLINE> <BLANKLINE> <p> Hello from <b>user slot</b> <BLANKLINE> </p> </body> </html>
清理
>>> del getRootFolder()['manfred']
与常规 Zope 页面模板的区别
宏的引用方式不同。请参阅上面的适当部分。
默认情况下,表达式以Python模式解析。这意味着,您必须使用tal:content="view.value",而不是tal:content="view/value"。现在,所有以python:开始的TAL表达式现在可以通过跳过此标记来缩短。
变更记录
4.0 (2023-02-09)
取消对 Python 2.7、3.4、3.5、3.6 的支持。
添加对 Python 3.7、3.8、3.9、3.10、3.11 的支持。
3.0.1 (2018-01-12)
重新排列测试,以便 Travis CI 可以获取所有功能测试。
3.0.0 (2018-01-11)
Python 3 兼容性。
1.0.4 (2014-07-29)
使用 Chameleon 2.10 或更高版本改进翻译机制的性能。
1.0.3 (2012-10-12)
修复使用 Chameleon 2.9 或更高版本时损坏的翻译。
1.0.2 (2012-05-07)
由于没有使用 z3c.pt PageTemplateFile 基类,相对于模块查找模板文件的行为丢失了。这已被修复。
1.0.1 (2012-05-03)
确保定义了最小版本要求。
1.0 (2012-05-01)
在版本 1.0rc4 中丢失了 target_language 混淆。从 z3c.pt 复制。
1.0rc4 (2012-01-03)
升级到最新的 Chameleon 2.7.1
直接从 Chameleon 使用一些组件/表达式,而不是 z3c.pt
1.0rc3 (2011-07-14)
将 megrok.chameleon 重命名为 grokcore.chameleon,使其成为 Grok 的官方部分。
早期版本
早期版本的 grokcore.chameleon 以 megrok.chameleon 的名称出现。
项目详情
下载文件
下载适合您平台的文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。
源分布
构建版本
grokcore.chameleon-4.0.tar.gz 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | d26f1074f014cd4710c59d177b6bbf8477d3b16c134d545e6faddd8eeb5f7a59 |
|
MD5 | bd3e5e932bce7050fc63c4dab3a50516 |
|
BLAKE2b-256 | aaea688acefde2fbb8a0c920db137cacce5adae1bcd9279f82a55f9082d9f534 |
grokcore.chameleon-4.0-py3-none-any.whl 的哈希值
算法 | 哈希摘要 | |
---|---|---|
SHA256 | 360608bd52a27ef7da172fd89a4f1fad6a08de57487f0fd934329a1f5bd86388 |
|
MD5 | 652555f7a639e9e8c9975f49dbc11613 |
|
BLAKE2b-256 | 04d58483cf26e3213624cb4fb2968829fc27c4aeb619d51b3a6f7dbda61d1634 |