利用diazo,讓每個目錄設定自己的版型

Diazo用在plone上,提供設計師很強大的工具,可以將版型設計與plone的開發知識進一步抽離,對於設計一個網站的版型有效降低了設計師的進入門檻

不過Diazo實作上,必需事先指定theme所使用的html檔案,例如:

<theme href="index.html" />

另一方面,diazo所開發版型以模組的方式存在於系統中,選擇所要的版型必需由具有權限的帳號(如系統管理員)來決定,並且一次只能選擇一種版型。

這使得在版型的使用上多了一些限制,例如想要像一般blog一樣,由使用者自行決定家目錄的版型,就是個困難的任務。

本文利用 diazo 中的設定檔 manifest.cfg 結合 browserview 的技巧,企圖解決這樣的需求。

步驟一:

在manifest.cfg中,有如下內容

[theme]
title = SelectableTheme
description = Selectable Theme
doctype = <!DOCTYPE html>
prefix = {$portal_url}/++theme++diazo.exampletheme/{$themeid}

[theme:parameters]
portal_url = portal_state/portal_url
themeid = context/@@get_theme_id

其中 prefix = {$portal_url}/++theme++diazo.exampletheme/{$themeid} 使用了變數 {$themeid}

而 themeid 的值則由 browserview get_theme_id 來決定 (themeid = context/@@get_theme_id)

 

步驟二:新增一個 Dexterity content type,

class IThemeContent(form.Schema, IImageScaleTraversable):
    """
    Theme content
    """

這個 content type,沒有其他內容,我們只是要利用他來建立可選的版型名稱,之後會利用 title 欄位來辨識所需要的 themeid

 

步驟三:在 Folder 中新增欄位

為 Folder 新增一個關聯欄位,如下

    selectTheme = RelationChoice(
        title=_(u'Select theme'),
        description=_(u'Select theme for this folder.'),
        source=ObjPathSourceBinder(object_provides=IThemeContent.__identifier__),
        default=None,
        required=False,
    )

 

步驟四:

寫一個 browserview, GetThemeId 如下(範例使用grok):

class GetThemeId(grok.View):
    """ get selectTheme value, default value is 'porto' """

    grok.context(Interface)
    grok.require('zope2.View')
    grok.name('get_theme_id')

    def render(self):
        catalog = self.context.portal_catalog
        folder = self.context
        while folder.Type() not in ['Folder', 'Plone Site', 'WebProfile']:
            folder = folder.getParentNode()
        theme = getattr(folder, 'selectTheme', None)
        if theme is not None:
            themeId = theme.to_object.getId()
        else:
            try:
                homepage = catalog({'Type':'WebProfile', 'id':'index_html'})[0]
                themeId = homepage.selectTheme
            except:
                themeId = 'porto'
        return themeId

 

步驟五:

在 rules.xml 中,加入 xmlns:xi="http://www.w3.org/2001/XInclude" ,使得 rules.xml 內容如下:

<?xml version="1.0" encoding="UTF-8"?>
<rules
    xmlns="http://namespaces.plone.org/diazo"
    xmlns:css="http://namespaces.plone.org/diazo/css"
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xi="http://www.w3.org/2001/XInclude">

    <!-- Apply the following rules to standard Plone pages -->

    <rules if="$themeid = 'jollyness'">
        <xi:include href="jollyness.xml" />
    </rules>

    <rules if="$themeid = 'porto'">
        <xi:include href="porto.xml" />
    </rules>

    <rules if="$themeid = 'meteor'">
        <xi:include href="meteor.xml" />
    </rules>

</rules>

步驟六:

 依照一般 rules.xml 的語法,編輯各個 xml 檔案,如 porto.xml、meteor.xml...

 

到此大致完成,之後我們有完成的 theme,就可以利用 ThemeContent content type, 新增一個相同名稱的項目,讓 Folder可以選擇

如此,就可以完成像 blog 一般,讓每個使用者為自己的家目錄選擇所要的版型了。