Grok页面模板支持Chameleon
项目描述
megrok.chameleon
megrok.chameleon 允许在Grok中使用Chameleon模板。
目前提供了对Chameleon Genshi模板和Chameleon Zope页面模板的支持。
有关Grok和Chameleon模板的更多信息,请参阅
需求
Chameleon模板(Chameleon)。
Chameleon genshi模板(chameleon.genshi)。
Grok v1.0a1或更高版本,或five.grok 1.0或更高版本。
安装
要使用Chameleon页面模板与Grok,您只需要安装megrok.chameleon作为egg并包含其ZCML。最好将megrok.chameleon作为您的应用程序的依赖项,通过将其添加到setup.cfg中的install_requires列表中来实现。如果您使用grokproject创建应用程序,则setup.py位于项目根目录。它看起来可能像这样
install_requires=['setuptools', 'megrok.chameleon', # Add extra requirements here ],
然后,在您的configure.zcml中包含megrok.chameleon。如果您使用grokproject创建应用程序,它位于src/<projectname>/configure.zcml。在grok的包含行之后,但在当前包的grokking之前添加包含行。它看起来可能像这样
<include package="grok" /> <include package="megrok.chameleon" /> <grok:grok package="." />
如果您在configure.zcml中使用autoInclude,则不需要进行此后续步骤。
然后再次运行bin/buildout。现在您应该会看到buildout显示类似于以下内容的信息
Getting distribution for 'megrok.chameleon'. Got megrok.chameleon 0.5.
就这些了。现在您可以在Grok应用程序中使用Chameleon页面模板了。
使用
megrok.chameleon支持Grok标准,将模板放在模板目录中,例如app_templates,因此您可以通过在模板目录中放置Chameleon Genshi模板或Chameleon Zope页面模板来使用Chameleon页面模板,就像使用常规ZPT模板一样。尽管Chameleon模板本身没有模板文件扩展名的标准,但Grok需要将扩展名与类型关联起来,以便知道每个模板的类型。megrok.chameleon定义了以下扩展名
.cpt(Chameleon页面模板)用于Chameleon页面模板
.cg(Chameleon genshi模板)用于由Chameleon驱动的Genshi模板
.cgt(Chameleon genshi文本模板)用于由Chameleon驱动的Genshi文本模板
您还可以内联使用Chameleon页面模板。这种语法的例子是
from megrok.chameleon.components import ChameleonPageTemplate index = ChameleonPageTemplate('<html>the html code</html>')
或者如果您使用文件
from megrok.genshi.components import ChameleonPageTemplateFile index = ChameleonPageTemplateFile(filename='thefilename.html')
详细描述
支持使用Chameleon驱动的模板的Grok。
使用megrok.chameleon,您可以使用由Chameleon解析和渲染的模板。目前支持Zope页面模板和Genshi模板。
Chameleon Zope页面模板
Chameleon为Zope页面模板提供支持,可以使用带有.cpt(=Chameleon Page Template)文件扩展名的.cpt文件从grok编写模板。
Chameleon页面模板与标准Zope页面模板在几个方面有所不同,最值得注意的是
默认情况下,表达式通过Python-mode进行解析。这意味着,您必须使用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')
我们注册一切。在我们能够理解我们的测试用例之前,我们必须理解megrok.chameleon包。这样,新的模板类型就会通过框架注册
>>> import grokcore.view >>> grokcore.view.testing.grok('megrok.chameleon') >>> grokcore.view.testing.grok('megrok.chameleon.tests.cpt_fixture')
我们创建一个庞然大物,它应该提供大量由Chameleon页面模板驱动的视图,并将其放入数据库中以设置位置信息
>>> from megrok.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') >>> print open(cavepainting_cpt, 'rb').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及其方法和属性。food视图正是这样做的。模板看起来像这样
>>> food_cpt = os.path.join(template_dir, 'food.cpt') >>> print open(food_cpt, 'rb').read() <html> <body> <span tal:define="foo 'a FOO'"> ${view.me_do()} <span tal:replace="structure view.me_do()" /> CSS-URL: ${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: http://127.0.0.1/@@/megrok.chameleon.tests.cpt_fixture/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!>,但前者直接而简洁地完成,而后者对字符串执行额外的HTML编码。因此,这两个表达式的输出不同。对于前者表达式是
<ME GROK EAT MAMMOTH!>
而对于后者是
<ME GROK EAT MAMMOTH!>
。
支持变量
每个模板至少提供以下变量
- 模板
模板实例
- 视图
关联的视图
- 上下文
视图的上下文
- 请求
当前请求
- 静态
应用程序的静态目录
正如我们所见,当我们查看我们测试用例中的vars.cpt并对其进行渲染时
>>> cpt_file = os.path.join(template_dir, 'vars.cpt') >>> print open(cpt_file, 'rb').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} <BLANKLINE> static (the static dir of the application): ${static} </body> </html>
。
>>> view = getMultiAdapter((manfred, request), name='vars') >>> print view() <html> <body> This template knows about the following vars: <BLANKLINE> template (the template instance): <vars template in ...vars.cpt> <BLANKLINE> view (the associated view): <megrok.chameleon.tests.cpt_fixture.app.Vars object at 0x...> <BLANKLINE> context (the context of the view): <megrok.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 <BLANKLINE> static (the static dir of the application): <grokcore.view.components.DirectoryResource object at 0x...> </body> </html>
内联模板
我们还可以定义内联模板。在我们的app.py中,我们定义了一个内联模板,如下所示
from megrok.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表达式
从megrok.chameleon 0.5版本开始,我们部署了完整的Chameleon包。
模板中支持的TAL/TALES表达式取决于Chameleon的安装版本,同时我们支持一些额外的与Zope相关的TALES表达式。
所有支持的表达式和语句的列表可以在chameleon.zpt文档中找到。由megrok.chameleon提供的额外TALES表达式包括
- 存在
告诉一个名称是否存在于模板的命名空间中。
- 非
将尾随表达式评估为布尔值并对其进行反转。
- 路径
将尾随表达式作为路径处理,而不是作为Python表达式。
- 提供者
支持视图小部件提供者。
在我们的app.py中,我们定义了一个特殊的视图来显示一些特殊表达式。这也包括一个视图小部件
import grok from megrok.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') >>> print open(cpt_file, 'rb').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>
宏
使用megrok.chameleon,我们还可以使用宏,尽管它与常规的Zope页面模板略有不同。
我们可以这样定义宏:
>>> cpt_file = os.path.join(template_dir, 'macromaster.cpt') >>> print open(cpt_file, 'rb').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') >>> print open(cpt_file, 'rb').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-mode进行解析。这意味着,您必须使用tal:content="view.value"而不是tal:content="view/value"。现在,以python:开头的TAL表达式的每个出现都可以通过跳过此标记来缩短。
Chameleon Genshi模板
Chameleon提供了对Genshi模板的支持,可以使用具有.cg文件扩展名的grok编写模板。
Genshi文本模板可以使用.cgt文件扩展名。
注意,chameleon genshi模板可能不涵盖原生genshi解析器提供的全部功能。如果您想使用原生genshi支持,请使用megrok.genshi。
有关更多信息,请参阅chameleon.genshi页面。
先决条件
在我们能够看到模板的实际效果之前,我们关注正确的注册并设置一些使用的变量
>>> import os >>> testdir = os.path.join(os.path.dirname(__file__), 'tests') >>> genshi_fixture = os.path.join(testdir, 'genshi_fixture') >>> template_dir = os.path.join(genshi_fixture, 'app_templates')
我们注册一切。在我们能够理解我们的测试用例之前,我们必须理解megrok.chameleon包。这样,新的模板类型就会通过框架注册
>>> grokcore.view.testing.grok('megrok.chameleon') >>> grokcore.view.testing.grok('megrok.chameleon.tests.genshi_fixture')
我们创建了一个巨大的mammoth,它应该为我们提供大量的Genshi驱动视图,并将其放入数据库中设置位置信息。
>>> from megrok.chameleon.tests.genshi_fixture.app import Mammoth >>> manfred = Mammoth() >>> getRootFolder()['manfred'] = manfred
此外,我们为获取关于Manfred的不同视图做好准备
>>> from zope.publisher.browser import TestRequest >>> from zope.component import getMultiAdapter >>> request = TestRequest()
简单模板
我们准备了一个简单的洞穴壁画视图。模板看起来像这样
>>> cavepainting_cg = os.path.join(template_dir, 'cavepainting.cg') >>> print open(cavepainting_cg, 'rb').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及其方法和属性。food视图正是这样做的。模板看起来像这样
>>> food_cg = os.path.join(template_dir, 'food.cg') >>> print open(food_cg, 'rb').read() <html> <body> ${view.me_do()} CSS-URL: ${static['test.css']()} My context is: ${view.url(context)} </body> </html>
渲染后的视图看起来像这样
>>> view = getMultiAdapter((manfred, request), name='food') >>> print view() <html> <body> ME GROK EAT MAMMOTH! CSS-URL: http://127.0.0.1/@@/megrok.chameleon.tests.genshi_fixture/test.css My context is: http://127.0.0.1/manfred </body> </html>
包含其他模板
有了genshi支持,我们还可以包含其他模板。gatherer视图看起来像这样:
>>> gatherer_cg = os.path.join(template_dir, 'gatherer.cg') >>> print open(gatherer_cg, 'rb').read() <html xmlns:xi="http://www.w3.org/2001/XInclude"> <body> ME GROK GATHER BERRIES! <xi:include href="berries.cg"/> </body> </html>
显然,这里包含了一个名为berries.cg的模板。它看起来像这样:
>>> berries_cg = os.path.join(template_dir, 'berries.cg') >>> print open(berries_cg, 'rb').read() <strong>Lovely blueberries!</strong>
当我们渲染前一个模板时,我们得到:
>>> view = getMultiAdapter((manfred, request), name='gatherer') >>> print view() <html> <body> ME GROK GATHER BERRIES! <strong>Lovely blueberries!</strong> </body> </html>
文本模板
也支持genshi文本模板。我们有一个看起来是这样的模板:
>>> hunter_cgt = os.path.join(template_dir, 'hunter.cgt') >>> print open(hunter_cgt, 'rb').read() ME GROK HUNT ${view.game}!
注意,此模板具有.cgt (= c cameleon g genshi t text template)文件扩展名。
如果我们渲染它,所有表达式都被替换。
>>> view = getMultiAdapter((manfred, request), name='hunter') >>> print view() ME GROK HUNT MAMMOTH!!
变更日志
0.5.2 (2010-07-19)
移除对chameleon.genshi的依赖,因为它现在已包含在Chameleon中。
0.5.1 (2010-05-20)
使ITranslatorExpressions的注册条件化:如果同时安装了z3c.pt,则不注册我们自己的。这应该可以解决使用megrok.chameleon与其他需要z3c.pt的包(如z3c.form和grok-ecosphere的依赖包)时出现的DuplicationError。
为测试移除zope.testing、zope.app.testing和z3c.testsetup。
0.5 (2010-03-03)
添加了测试以展示使用megrok.chameleon宏的用法。
通过复制相关部分并本地注册,移除了对z3c.pt的依赖。
删除了对exists('varname')表达式的支持。仍然可以使用常规的TALES表达式exists: varname/path。
改为使用Chameleon而不是chameleon.*包。
0.4 (2010-02-23)
将megrok声明为命名空间包。
在ftesting.zcml中修复了包含顺序。
将纯测试需求移入自己的setup-section,以减少常规(非测试)模式下的依赖。
0.3 (2010-02-14)
添加了许可文件。
0.2 (2009-09-18)
从模板提供宏访问。
不要再依赖grok,而只使用grokcore.view。
在页面模板中增加了对path()和exists()的支持。这是从z3c.pt引入的。
修复ZCML包含。
0.1 (2009-02-22)
初始发布
项目详情
megrok.chameleon-0.5.2.tar.gz的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | a6084266f92b36599732c5f89f8d72eb826e63db589fe0b61c9a66ff975d3ba0 |
|
MD5 | 7d440eb1f16f153bf0db015c6a37b15d |
|
BLAKE2b-256 | d45392f5256c9c6afba3c2cc6127e4fab85a4f107923be6fed3e11c620f9e585 |