为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://127.0.0.1/@@/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://127.0.0.1/@@/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://127.0.0.1/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://127.0.0.1/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://127.0.0.1/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://127.0.0.1/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://127.0.0.1/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://127.0.0.1/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)
初始公开发布。