跳转到主要内容

Quintagroup主题模板,用于Plone 3,具有嵌套命名空间

项目描述

qplone3主题模板

quintagroup.themetemplate是Zopeskel的“Plone 3主题”模板的增强版本,包含addcontent本地命令,允许您通过添加附加元素来扩展基本Plone主题,例如:皮肤层、组件、视图、CSS和JS资源,以及zexp文件中的对象。这个包在功能上相当于Archetype模板。

quintagroup.themetemplate包用于开发所有Quintagroup的Plone 3主题,地址为http://skins.quintagroup.com

Quintagroup的Plone主题, 2006-2012

内容

  1. 概述

  2. 创建主题包

  3. 扩展主题

  4. 发布说明

概述

此主题模板允许您创建初始主题包骨架,即创建具有嵌套命名空间的plone3主题Python包(这与Zopeskel中的默认plone3_theme模板不同)

之后,您可以通过以下元素扩展主题包

  • 皮肤层

  • 组件

  • 视图

  • CSS、JS资源

  • zexp文件中的对象

使用paster create PasteScript命令创建包。使用扩展此产品的paster addcontent本地ZopeSkel命令(扩展资源)扩展主题

创建主题包

让我们创建plone-3主题Python包。使用paster create命令

>>> paster('create -t qplone3_theme quintagroup.theme.example --no-interactive --overwrite')
paster create -t qplone3_theme quintagroup.theme.example --no-interactive
...

您将获得包含以下内容的标准Python包内容

  • quintagroup 顶级命名空间。

  • quintagroup.theme.example-configure.zcml - 添加到package-includes目录的zcml文件

检查一下

>>> package_dir = 'quintagroup.theme.example'
>>> objects = ['setup.py', 'quintagroup', 'quintagroup.theme.example-configure.zcml']
>>> objects.sort()
>>> [o for o in objects if o in os.listdir(package_dir)]
['quintagroup', 'quintagroup.theme.example-configure.zcml', 'setup.py']

qplone3_theme 模板 - 创建具有嵌套命名空间的主题。

默认情况下 - 主题位于 quintagroup.theme.<包名第三部分> 命名空间

在我们的例子中 - quintagroup.theme.example

因此请检查命名空间

>>> theme_namespace = os.path.join(package_dir,'quintagroup','theme','example')
>>> os.path.isdir(theme_namespace)
True

主题包含 3 个子目录(browser、profiles、skins)

>>> cd(theme_namespace)
>>> dirs = ('skins', 'browser', 'profiles')
>>> [True for d in dirs if d in os.listdir('.')]
[True, True, True]

以及初始化文件(__init__.py、configure.zcml)

>>> files = ('__init__.py', 'configure.zcml')
>>> [True for d in files if d in os.listdir('.')]
[True, True]

browser 目录

Browser 目录包含

  • ‘templates’ 资源目录

  • 包含 IThemeSpecific 标记接口的 interfaces.py 模块

  • configure.zcml,其中注册了主题标记接口

    >>> ls('browser')
    __init__.py
    configure.zcml
    interfaces.py
    templates
    
    >>> cat('browser/interfaces.py')
    from plone.theme.interfaces import IDefaultPloneLayer
    <BLANKLINE>
    class IThemeSpecific(IDefaultPloneLayer):
    ...
    
    >>> cat('browser/configure.zcml')
    <configure
    ...
        <interface
            interface=".interfaces.IThemeSpecific"
            type="zope.publisher.interfaces.browser.IBrowserSkinType"
            name="Custom Theme"
            />
    ...

正如我们所见,默认主题名称是“Custom Theme”,但在创建主题时,您可以指定自己的名称。查看这个...

首先创建具有不同皮肤名称的配置文件

>>> conf_data = """
... [pastescript]
... skinname=My Theme Name
... """
>>> file('theme_config.conf','w').write(conf_data)

使用您自己的皮肤名称创建相同的主题并检查此操作

>>> paster('create -t qplone3_theme quintagroup.theme.example --no-interactive --overwrite --config=theme_config.conf')
paster create ...
>>> cd(package_dir)
>>> cat('quintagroup/theme/example/browser/configure.zcml')
<configure
...
    <interface
        interface=".interfaces.IThemeSpecific"
        type="zope.publisher.interfaces.browser.IBrowserSkinType"
        name="My Theme Name"
        />
...

skins 目录

它只包含 README.txt 文件,还没有皮肤层。这是 localcommand 的工作;)

但是请检查我是否正确...

>>> cd('quintagroup/theme/example')
>>> ls('skins')
README.txt

profiles 目录

包含“default”和卸载配置文件

>>> 'default' in os.listdir('profiles')
True
>>> 'uninstall' in os.listdir('profiles')
True

默认配置文件中包含以下内容

  • import_steps.xml - 任何原因。

  • skins.xml - 注册皮肤目录

    >>> cd('profiles/default')
    >>> 'import_steps.xml' in os.listdir('.')
    True
    >>> 'skins.xml' in os.listdir('.')
    True

skins.xml 配置文件使主题在安装时默认,并使用来自“Plone Default”的主题层列表,没有任何新层(目前还没有)

>>> cat('skins.xml')
<?xml version="1.0"?>
...
<object name="portal_skins" ...
        default_skin="My Theme Name">
...
<skin-path name="My Theme Name" based-on="Plone Default">
  <!-- -*- extra layer stuff goes here -*- -->
<BLANKLINE>
</skin-path>
...

import_steps.xml - 从 _setuphandlers.py_ 模块调用 _setupVarious_ 函数以进行附加安装步骤

>>> cat('import_steps.xml')
<?xml version="1.0"?>
...
<import-step id="quintagroup.theme.example.various"
...
             handler="quintagroup.theme.example.setuphandlers.setupVarious"
...
</import-step>
...

查看 setuphandlers.py 模块

>>> cd('../..')
>>> cat('setuphandlers.py')
    def setupVarious(context):
...

扩展主题

ZopeSkel 包带来的最佳特性之一是 localcommand

这部分显示了如何使用附加的有用功能扩展主题(使用 qplone3_theme ZopeSkel 模板生成)

  • 皮肤层

  • 视图

  • 小部件

  • 小部件

  • CSS

  • JavaScript

  • zexp文件中的对象

因此,在 qplone3_theme 生成的包中,您可以使用 addcontent ZopeSkel 本地命令。

注意:localcommand(在我们的例子中为 addcontent)应在生成的主题包的任何子目录中调用。它将不会在这个包之外工作

>>> paster('addcontent -a')
paster addcontent -a
  ...
    css_dtml_skin:   A DTML file in skin layer with CSS registration
    css_resource:    A Plone 3 CSS resource template
  ...
    import_zexps:    A template for importing zexp-objects into portal on installation
    js_resource:     A Plone 3 JS resource template
  N portlet:         A Plone 3 portlet
  ...
    skin_layer:      A Plone 3 Skin Layer
  ...
  N view:            A browser view skeleton
    viewlet_hidden:  A Plone 3 Hidden Viewlet template
    viewlet_order:   A Plone 3 Order Viewlet template
  ...

我们可以看到可用于我们主题的扩展子模板列表。‘N’ 字符告诉我们这些子模板已注册用于其他(原型)模板,但这无关紧要 - 它们可以正确扩展我们的主题。

添加 SKIN LAYER

为此,使用 skin_layer 子模板和 addcontent 本地命令

>>> paster('addcontent --no-interactive skin_layer')
paster addcontent --no-interactive skin_layer
Recursing into profiles
...

此命令将新的‘skin_layer’(默认名称)目录添加到 _skins_ 目录中,其中包含仅有的 CONTENT.txt 文件

>>> 'skin_layer' in os.listdir('skins')
True
>>> ls('skins/skin_layer')
CONTENT.txt

skins.xml 配置文件也进行了更新

>>> cat('profiles/default/skins.xml')
<?xml version="1.0"?>
...
<object name="portal_skins" allow_any="False" cookie_persistence="False"
   default_skin="My Theme Name">
...
 <object name="skin_layer"
    meta_type="Filesystem Directory View"
    directory="quintagroup.theme.example:skins/skin_layer"/>
...
 <skin-path name="My Theme Name" based-on="Plone Default">
...
  <layer name="skin_layer"
     insert-after="custom"/>
<BLANKLINE>
 </skin-path>
...

我们可以看到

  • skin_layer 目录被注册为文件系统目录视图

  • skin_layer 文件系统目录视图被添加到我们的主题层列表中

添加 PORTLET

在添加新的小部件之前,小部件目录中只有初始化文件可用

>>> ls('portlets')
__init__.py
configure.zcml

使用 portlet 子模板添加小部件

>>> paster('addcontent --no-interactive portlet')
paster addcontent --no-interactive portlet
...
Recursing into portlets
...

执行此本地命令后...

主题根目录中的 configure.zcml 文件 - 包括小部件注册

>>> cat('configure.zcml')
<configure
...
<include package=".portlets" />
...

exampleportlet.pt 模板和 exampleportlet.py 脚本添加到小部件目录中

>>> files = ('exampleportlet.pt', 'exampleportlet.py')
  >>> [True for d in files if d in os.listdir('portlets')]
  [True, True]

并且 portlets/configure.zcml - 注册新小部件

>>> cat('portlets/configure.zcml')
<configure
...
     <plone:portlet
         name="quintagroup.theme.example.portlets.ExamplePortlet"
         interface=".exampleportlet.IExamplePortlet"
         assignment=".exampleportlet.Assignment"
         view_permission="zope2.View"
         edit_permission="cmf.ManagePortal"
         renderer=".exampleportlet.Renderer"
         addview=".exampleportlet.AddForm"
         editview=".exampleportlet.EditForm"
         />
...

最后,新小部件类型在 portlets.xml 配置文件中注册

>>> cat('profiles/default/portlets.xml')
<?xml version="1.0"?>
...
   <portlet
     addview="quintagroup.theme.example.portlets.ExamplePortlet"
     title="Example portlet"
     description=""
     i18n:attributes="title; description"
     />
...

感谢 ZopeSkel 开发者为此子模板;)

添加 CSS 资源

使用 css_resource 子模板

>>> paster("addcontent --no-interactive css_resource")
paster addcontent --no-interactive css_resource
Recursing into browser
...
Recursing into profiles
...

此模板将(如果尚不存在)_stylesheets_ 目录添加到 _browser_ 目录中

>>> 'stylesheets' in os.listdir('browser')
True

在 _stylesheets_ 资源目录中添加了空的 main.css 样式表资源

>>> 'main.css' in os.listdir('browser/stylesheets')
True
>>> cat('browser/stylesheets/main.css')
<BLANKLINE>

新的资源目录在 configure.zcml 中注册

>>> cat('browser/configure.zcml')
<configure
...
    <browser:resourceDirectory
        name="quintagroup.theme.example.stylesheets"
        directory="stylesheets"
        layer=".interfaces.IThemeSpecific"
        />
...

并且 cssregistry.xml 配置文件被添加到 profiles/default 目录中,其中注册了 main.css 样式表

>>> 'cssregistry.xml' in os.listdir('profiles/default')
True
>>> cat('profiles/default/cssregistry.xml')
<?xml version="1.0"?>
<object name="portal_css">
<BLANKLINE>
 <stylesheet title=""
    id="++resource++quintagroup.theme.example.stylesheets/main.css"
    media="screen" rel="stylesheet" rendering="inline"
    cacheable="True" compression="safe" cookable="True"
    enabled="1" expression=""/>
...

将 CSS 资源作为 dtml-file 添加到皮肤层中

此模板实际上与上一个模板完全相同,但添加了 layer_name 变量,用于指定要在其中添加 css dtml-file 的皮肤层。当然,css 资源被添加到指向 skins/<layer_name>/<css_reseource_name>.dtml 文件的 skins 目录中。

此子模板在将CSS注册为资源层之前具有多个优点

  • 在dtml文件中,您可以使用dtml语言的强大功能

  • 如果需要,客户可以覆盖此资源

重要:要向注册的皮肤层添加CSS资源,您应与skin_layer子模板一起使用此子模板。

使用css_dtml_skin子模板

>>> paster("addcontent --no-interactive css_dtml_skin")
paster addcontent --no-interactive css_dtml_skin
Recursing into profiles
...
Recursing into skins
...

此模板将main.css.dtml文件添加到skins/skin_layer文件夹

>>> 'main.css.dtml' in os.listdir('skins/skin_layer')
True

main.css.dtml文件已准备好作为dtml文档使用

>>> cat('skins/skin_layer/main.css.dtml')
/*
...
/* <dtml-with base_properties> (do not remove this :) */
...
/* </dtml-with> */
<BLANKLINE>

并且 cssregistry.xml 配置文件被添加到 profiles/default 目录中,其中注册了 main.css 样式表

>>> 'cssregistry.xml' in os.listdir('profiles/default')
True
>>> cat('profiles/default/cssregistry.xml')
<?xml version="1.0"?>
<object name="portal_css">
<BLANKLINE>
 <stylesheet title=""
    id="++resource++quintagroup.theme.example.stylesheets/main.css"
    media="screen" rel="stylesheet" rendering="inline"
    cacheable="True" compression="safe" cookable="True"
    enabled="1" expression=""/>
...

添加JAVASCRIPT资源

使用js_resource子模板

>>> paster('addcontent --no-interactive js_resource')
paster addcontent --no-interactive js_resource
Recursing into browser
...
Recursing into profiles
...

此模板将(如果尚不存在)在_browser_目录中添加_scripts_目录

>>> 'scripts' in os.listdir('browser')
True

在_scripts_目录中添加了空的foo.js JavaScript文件

>>> 'foo.js' in os.listdir('browser/scripts')
True
>>> cat('browser/scripts/foo.js')
<BLANKLINE>

如果尚未注册,新资源目录已在configure.zcml中注册

>>> cat('browser/configure.zcml')
<configure
...
    <browser:resourceDirectory
        name="quintagroup.theme.example.scripts"
        directory="scripts"
        layer=".interfaces.IThemeSpecific"
        />
...

在profiles/default目录中添加了cssregistry.xml配置文件(如果尚不存在),并注册了新的foo.js JavaScript资源

>>> 'jsregistry.xml' in os.listdir('profiles/default')
True
>>> cat('profiles/default/jsregistry.xml')
<?xml version="1.0"?>
<object name="portal_javascripts">
...
 <javascript
    id="++resource++quintagroup.theme.example.scripts/foo.js"
    inline="False" cacheable="True" compression="safe"
    cookable="True" enabled="1"
    expression=""
    />
...

测试视图子模板

视图子模板有两种类型

  • viewlet_order

  • viewlet_hidden

第一个用于添加新视图并设置ViewletManager的视图顺序,第二个仅隐藏指向的ViewletManager中的视图。

有序的新视图

使用viewlet_order子模板

>>> paster('addcontent --no-interactive viewlet_order')
paster addcontent --no-interactive viewlet_order
Recursing into browser
...
Recursing into templates
...
Recursing into profiles
...

此模板将在_browser_目录中添加(如果不存在;)_viewlets.py_模块。添加了Example ViewletBase类,该类绑定到templates/example_viewlet.pt模板

>>> 'viewlets.py' in os.listdir('browser')
True

>>> cat('browser/viewlets.py')
from Products.CMFCore.utils import getToolByName
from Products.Five.browser.pagetemplatefile import ViewPageTemplateFile
from plone.app.layout.viewlets import common
...
class Example(common.ViewletBase):
    render = ViewPageTemplateFile('templates/example_viewlet.pt')
<BLANKLINE>

检查templates目录中的模板文件

>>> 'example_viewlet.pt' in os.listdir('browser/templates')
True
>>> cat('browser/templates/example_viewlet.pt')
<BLANKLINE>

新视图已在configure.zcml中注册

>>> cat('browser/configure.zcml')
<configure
...
   <browser:viewlet
        name="quintagroup.theme.example.example"
        manager="plone.app.layout.viewlets.interfaces.IPortalHeader"
        class=".viewlets.Example"
        layer=".interfaces.IThemeSpecific"
        permission="zope2.View"
        />
...

viewlets.xml配置文件已添加到profiles/default目录,其中包含新的视图注册,并按指定的视图管理器排序

>>> 'viewlets.xml' in os.listdir('profiles/default')
True
>>> cat('profiles/default/viewlets.xml')
<?xml version="1.0"?>
<object>
...
 <order manager="plone.portalheader"
         based-on="Plone Default"
         skinname="My Theme Name" >
...
    <viewlet name="quintagroup.theme.example.example" insert-after="*" />
<BLANKLINE>
  </order>
<BLANKLINE>
</object>

隐藏现有的视图

在这种情况下,您可以使用viewlet_hidden子模板

>>> paster('addcontent --no-interactive viewlet_hidden')
paster addcontent --no-interactive viewlet_hidden
Recursing into profiles
...

如上日志所示,只有添加/更新配置文件的内容

profiles/default目录中有一个viewlet.xml配置文件,该文件隐藏了指定视图管理器中的视图

>>> 'viewlets.xml' in os.listdir('profiles/default')
True
>>> cat('profiles/default/viewlets.xml')
<?xml version="1.0"?>
<object>
...
  <hidden manager="plone.portalheader" skinname="My Theme Name">
...
    <viewlet name="example" />
<BLANKLINE>
  </hidden>
...
</object>

添加ZEXPs导入

想象一下这样的情况:您正在开发一个主题,该主题使用一些额外的门户对象(用于某些potlets的文本文档)。然后,您的主题客户可以根据他的需求编辑这些对象。

对于这种情况,存在import_zexps子模板。

import_zexps子模板通过在主题安装时将zexp格式文件的列表导入到门户根目录中的机制扩展了您的主题。

>>> paster('addcontent --no-interactive import_zexps')
paster addcontent --no-interactive import_zexps
...
Recursing into import
...
Recursing into profiles
...
Inserting from profiles.zcml_insert ...
...
Inserting from setuphandlers.py_insert into ...
...

如上日志所示

  • 在主题的根目录中添加了“import”目录

  • 更新了配置文件内容

  • 更新了profiles.zcml文件

  • 在setuphandlers.py模块中插入了一些内容

  1. 添加了空的“import”目录,您将在此目录中放置要安装到门户根目录的zexp对象。

    >>> ls('import')
    CONTENT.txt
  2. 在profiles/import_zexps目录中添加了import_steps.xml,其中包含额外的quintagroup.theme.example.import_zexps步骤

    >>> 'import_zexps' in os.listdir('profiles')
    True
    >>> 'import_steps.xml' in os.listdir('profiles/import_zexps')
    True
    
    >>> cat('profiles/import_zexps/import_steps.xml')
    <?xml version="1.0"?>
    ...
      <import-step id="quintagroup.theme.example.import_zexps"
                   version="..."
                   handler="quintagroup.theme.example.setuphandlers.importZEXPs"
                   title="My Theme Name: Import zexps objects">
        Import zexp objects into portal on My Theme Name theme installation
      </import-step>
    <BLANKLINE>
    ...
  3. 使用新的通用设置配置文件更新了profiles.zcml配置

    >>> cat('profiles.zcml')
    <configure
    ...
      <genericsetup:registerProfile
        name="import_zexps"
        title="My Theme Name: Import ZEXPs"
        directory="profiles/import_zexps"
        description='Extension profile for importing objects of the "My Theme Name" Plone theme.'
        provides="Products.GenericSetup.interfaces.EXTENSION"
        />
    <BLANKLINE>
    ...
  4. 检查setuphandlers.py模块 - 必须定义importZEXPs函数

    >>> cat('setuphandlers.py')
    def setupVarious(context):
    ...
    def importZEXPs(context):
    ...

然后只需准备zexp对象并将它们复制到import目录。

发布说明!

在发布主题之前,我建议清理setup.py脚本

  • 删除theme_vars参数(其值仅对主题开发有用)

  • 删除entry_points参数(同样原因)。目前对plone来说,它是无用的。

  • 还要删除paster_plugins参数(它在主题开发期间与entry_points一起使用时才有意义)

上述步骤可以防止主题分发/部署时可能出现的错误。

注意

  • quintagroup.themetemplate v0.25与ZopeSkel >= 2.15兼容

变更日志

0.25 (2010-06-24)

  • 修正了包的版本[mylan]

  • 解决了与ZopeSkel >= 2.15的不兼容性问题[mylan]

  • 更新了测试[mylan]

0.2.2(未发布)

  • 更新了import_zexps子模板 - 将此步骤移入单独的通用设置配置文件[mylan]

  • 为更新的import_zexps子模板更新了测试[mylan]

0.2(未发布)

  • 添加了新的css_dtml_skin子模板[mylan]

  • 为css_dtml_skin子模板添加了测试[mylan]

0.14(未发布)

  • 重构主题变量存储 - 现在存储在单独的theme_vars.cfg文件中,没有distutils编写器 [mylan]

  • 清理代码 [mylan]

0.11 (2009-04-13)

  • 移除setup.cfg [mylan]

0.10 (2009-04-13)

  • 更新README [olha]

0.9 (2009-04-11)

  • 更改包名/命名空间为quintagroup.themetemplate. [mylan]

0.8 (2009-04-10)

  • 更新测试,README [mylan]

  • 更新viewlet-order子模板 [mylan]

  • 修复卸载错误 [mylan]

0.7 (未发布)

  • 添加卸载配置文件以修复主题卸载后的皮肤工具 [piv]

0.1 (未发布)

  • 首次导入具有嵌套命名空间的Theme模板。支持ZopeSkel的“addcommand”本地命令来扩展Theme模板,支持使用portlet和本地模板进行扩展。[mylan]

项目详情


下载文件

下载适用于您的平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源代码分发

quintagroup.themetemplate-0.25.tar.gz (39.8 kB 查看哈希值)

上传时间 源代码

构建分发

quintagroup.themetemplate-0.25-py2.4.egg (65.1 kB 查看哈希值)

上传时间 源代码

支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面