为Grok提供静态资源库支持。
项目描述
megrok.resourcelibrary: Grok中的资源
简介
Grok已经自带了一种简单的方式来暴露静态文件资源,即static目录。
megrok.resourcelibrary允许在Grok中更灵活地包含静态文件资源。它使用zc.resourcelibrary包来完成此操作。
资源库本质上就像一个目录,例如包的static目录,里面充满了静态资源,如CSS文件、javascript文件和图像。资源旨在从HTML页面使用,作为显示特定布局或用户界面的额外资源。
megrok.resourcelibrary相对于Grok的默认static目录有哪些更灵活之处?
资源库可以在层中。
资源库可以有非公开权限。
资源库可以更容易地被其他库复用。资源库有开发者控制的独特名称。
资源库可以在特定小部件需要时自动将一些资源(如javascript或css)包含在网页的head部分。
资源库还可以依赖其他库。
基本示例
让我们看看这一切是如何工作的。首先,我们需要理解这个包本身(这通常是通过ZCML完成的)
>>> from grok.testing import grok
>>> grok('megrok.resourcelibrary.meta')
现在我们可以设置一个简单的资源库
>>> import grok
>>> import megrok.resourcelibrary
>>> class SomeLibrary(megrok.resourcelibrary.ResourceLibrary):
... megrok.resourcelibrary.directory('tests/example')
我们需要理解这一点,使其可用(在常规使用中,这会自动为您完成)
>>> from grok.testing import grok_component
>>> grok_component('SomeLibrary', SomeLibrary)
True
该目录中的资源现在已发布,默认情况下位于库的类名下,小写(因此为somelibrary)
>>> from zope.testbrowser.testing import Browser
>>> browser = Browser()
>>> browser.open('https:///@@/somelibrary/my-lib/included.js')
>>> print browser.contents
function be_annoying() {
alert('Hi there!');
}
默认名称可以通过使用 grok.name 指令来覆盖
>>> class SomeLibrary2(megrok.resourcelibrary.ResourceLibrary):
... grok.name('some-library')
... megrok.resourcelibrary.directory('tests/example')
>>> grok_component('SomeLibrary2', SomeLibrary2)
True
>>> browser.open('https:///@@/some-library/my-lib/included.js')
>>> print browser.contents
function be_annoying() {
alert('Hi there!');
}
指向一个不存在的目录是错误的
>>> class WrongDirectory(megrok.resourcelibrary.ResourceLibrary):
... grok.name('wrong-directory')
... megrok.resourcelibrary.directory('tests/doesnt_exist')
>>> grok_component('WrongDirectory', WrongDirectory)
Traceback (most recent call last):
...
GrokError: Directory 'tests/doesnt_exist' is not a valid directory passed to the 'wrong-directory' directive.
自动包含资源
我们现在设置了一个资源库,每次在网页中使用时,会自动包含两个资源,即 included.js 和 included.css
>>> class MyLib(megrok.resourcelibrary.ResourceLibrary):
... grok.name('my-lib')
... megrok.resourcelibrary.directory('tests/example/my-lib')
... megrok.resourcelibrary.include('included.js')
... megrok.resourcelibrary.include('included.css')
>>> grok_component('MyLib', MyLib)
True
这是如何在特定的页面模板中要求加载库的方法
<tal:block replace="resource_library:my-lib"/>
test_template_2 需要这个要求,所以应该包含相应的JavaScript
>>> browser.open('https:///zc.resourcelibrary.test_template_2')
>>> '/@@/my-lib/included.js' in browser.contents
True
资源也会被发布
>>> browser.open('/@@/my-lib/included.js')
>>> print browser.contents
function be_annoying() {
alert('Hi there!');
}
CSS的引用也被插入到HTML中
>>> browser.open('https:///zc.resourcelibrary.test_template_2')
>>> '/@@/my-lib/included.css' in browser.contents
True
CSS可以从引用的URL中获取
>>> browser.open('/@@/my-lib/included.css')
>>> print browser.contents
div .border {
border: 1px silid black;
}
以编程方式指示资源需求
在上面的示例中,我们演示了在ZPT中使用 resource_library 命名空间。库的使用也可以通过编程方式来指示,例如在视图中
>>> import grok
>>> from zope.interface import Interface
>>> class View(grok.View):
... grok.context(Interface)
... def render(self):
... MyLib.need()
... return '<html><head></head><body>Example</body></html>'
>>> grok_component('View', View)
True
>>> browser.open('https:///view')
>>> '/@@/my-lib/included.js' in browser.contents
True
这同样适用于没有显式 grok.name 的库
>>> class MyLib2(megrok.resourcelibrary.ResourceLibrary):
... megrok.resourcelibrary.directory('tests/example/my-lib')
... megrok.resourcelibrary.include('included.js')
... megrok.resourcelibrary.include('included.css')
>>> grok_component('MyLib2', MyLib2)
True
>>> class View2(grok.View):
... grok.context(Interface)
... def render(self):
... MyLib2.need()
... return '<html><head></head><body>Example</body></html>'
>>> grok_component('View2', View2)
True
>>> browser.open('https:///view2')
>>> '/@@/mylib2/included.js' in browser.contents
True
您也可以通过库名称来指示包含(就像在页面模板中所做的那样)
>>> class View3(grok.View):
... grok.context(Interface)
... def render(self):
... megrok.resourcelibrary.need('my-lib')
... return '<html><head></head><body>Example</body></html>'
>>> grok_component('View3', View3)
True
>>> browser.open('https:///view3')
>>> '/@@/my-lib/included.js' in browser.contents
True
使资源库依赖于其他资源库
我们可以使一个资源库依赖于另一个资源库
>>> class Dependency(megrok.resourcelibrary.ResourceLibrary):
... megrok.resourcelibrary.directory('tests/example')
... megrok.resourcelibrary.include('1.js')
>>> grok_component('Dependency', Dependency)
True
>>> class Dependent(megrok.resourcelibrary.ResourceLibrary):
... megrok.resourcelibrary.directory('tests/example')
... megrok.resourcelibrary.include('2.css')
... megrok.resourcelibrary.depend(Dependency)
>>> grok_component('Dependent', Dependent)
True
让我们创建一个需要 Dependent 的视图
>>> class DependentView(grok.View):
... grok.context(Interface)
... def render(self):
... Dependent.need()
... return '<html><head></head><body>Example</body></html>'
>>> grok_component('DependentView', DependentView)
True
现在将显示原始依赖项的包含代码
>>> browser.open('https:///dependentview')
>>> '/@@/dependency/1.js' in browser.contents
True
>>> '/@@/dependent/2.css' in browser.contents
True
保护资源
我们可以给资源一个权限
>>> class MyPermission(grok.Permission):
... grok.name("my.permission")
>>> grok_component('MyPermission', MyPermission)
True
>>> class MyLib3(megrok.resourcelibrary.ResourceLibrary):
... megrok.resourcelibrary.directory('tests/example/my-lib')
... grok.require(MyPermission)
>>> grok_component('MyLib3', MyLib3)
True
XXX 这还不工作,因为资源不执行自己的安全检查,而是依赖于代理,Grok 已经移除了……需要引入新的资源/工厂来手动执行检查。
变更
0.9.2 (2008-08-08)
Grokker 错误地依赖于(未导入)GrokImportError 在失败情况下。已将其更改为 GrokError 并添加了对其的测试。
将 use 指令重命名为 depend 并使其接受一个类参数而不是库名称。
0.9.1 (2008-08-06)
关闭 zip-safeness。
实际上添加一个 meta.zcml 来加载 grokker!
0.9 (2008-08-06)
初始公开发布。