2011/08/18

AddRemoveWidget and ComboBoxWidget

AddRemoveWidget permits to add self-entered data, which makes it a good replacement for KeywordWidget. Example code looks like:
from Products.AddRemoveWidget.AddRemoveWidget import AddRemoveWidget

...
atapi.LinesField(
'watershed',
storage=atapi.AnnotationStorage(),
widget=AddRemoveWidget(
label=_(u"Watershed"),
description=_(u"Enter one tag per line, multiple words allowed."),
),
vocabulary_factory='watershed',
),


AddRemoveWidget works with multiple-value fileds, if you need just single-value fields, try ComboBoxWidget instead. Example code looks like:
from Products.AddRemoveWidget.ComboBoxWidget import ComboBoxWidget

...

atapi.StringField(
'vote',
storage=atapi.AnnotationStorage(),
widget=ComboBoxWidget(
label=_(u"Best Band Ever"),
description=_(u"Single Choice."),
),
vocabulary=['The Beatles', 'The Smiths', 'Led Zeppelin', 'Joy Division'],
),


Look into the source code for more config options.

2011/08/17

Editing Plone Short Name

Short Name 可以譯成「識別碼」,它是構成 URL 的一部份,這個欄位在編輯時,預設是不顯示。如果網站包含整批具備流水編號的內容,例如想用 ISBN 當作識別碼,這類場合就適合在編輯時顯示識別碼欄位。
在 Plone Setup 的 Editing 設定項目,可以指定是否顯示 Short Name 欄位。

系統設定值勾選啟用後,還要確定使用者偏好設定,必須同步設定啟用才真的生效。

生效後的範例如下圖:

以 Archetype 的表單為例,Short Name 在程式碼內部使用 id 這個欄位名稱,剛新增時的網址會使用 book.2011-08-17.8631510722 之類的字串,如果 Short Name 欄位留空未填,那麼預設會使用 title-to-id 行為方式來更改 id 欄位值。

2011/08/09

Diazo Installation

在 Plone 裡安裝 Diazo 最簡單的方法,是搭配安裝 plone.app.theming,它需要 Plone 4.1 之後的環境,使用 4.1 版本的 Unified Installer 是最簡單的方法。
$ diff -Nu develop.cfg.orig develop.cfg

--- develop.cfg.orig 2011-08-09 22:21:25.495261571 +0800
+++ develop.cfg 2011-08-09 22:23:31.063243116 +0800
@@ -110,6 +110,7 @@
# we're extending buildout.cfg
extends =
buildout.cfg
+ http://good-py.appspot.com/release/plone.app.theming/1.0b8

extensions +=
mr.developer
@@ -117,6 +118,7 @@
eggs +=
Products.DocFinderTab
plone.reload
+ plone.app.theming

parts +=
test

$ bin/buildout -c develop.cfg

Uninstalling zopepy.
Uninstalling instance.
Installing _mr.developer.
Generated script '/home/marr/plone410/zinstance/bin/develop'.
Installing instance.
Getting distribution for 'plone.app.theming==1.0b8'.
Got plone.app.theming 1.0b8.
Getting distribution for 'repoze.xmliter==0.4'.
Got repoze.xmliter 0.4.
Getting distribution for 'plone.resource==1.0b5'.
Got plone.resource 1.0b5.
Getting distribution for 'plone.subrequest==1.6.1'.
Got plone.subrequest 1.6.1.
Getting distribution for 'diazo==1.0rc3'.
Got diazo 1.0rc3.
Getting distribution for 'experimental.cssselect==0.1'.
Got experimental.cssselect 0.1.
Generated script '/home/marr/plone410/zinstance/bin/instance'.
Installing zopepy.
Generated interpreter '/home/marr/plone410/zinstance/bin/zopepy'.
Updating zopeskel.
Installing omelette.
Updating backup.
Updating chown.
chown: Running echo Dummy references to force this to execute after referenced parts
echo /home/marr/plone410/zinstance/var/backups
chmod 600 .installed.cfg
find /home/marr/plone410/zinstance/var -type d -exec chmod 700 {} \;
chmod 744 /home/marr/plone410/zinstance/bin/*
Dummy references to force this to execute after referenced parts
/home/marr/plone410/zinstance/var/backups
Installing test.
Generated script '/home/marr/plone410/zinstance/bin/test'.
Updating repozo.
Updating unifiedinstaller.
*************** PICKED VERSIONS ****************
[versions]

*************** /PICKED VERSIONS ***************



2011/08/03

Development Eggs

When using paster to create "development eggs", there will install Paste, PasteScript, PasteDeploy eggs in Plone src directory. These eggs are for development purpose, will enable paster options like local commands. However, along with my.package.egg-info, they are not into version control repository.

2011/08/02

Vocabulary Import Tips

Run into this error:

ImportError: No module named schema.vocabulary

Fix it by changing the imports in vocabulary.py, from:

from zope.interface import implements
from zope.app.schema.vocabulary import IVocabularyFactory
from zope.schema.vocabulary import SimpleVocabulary

to:

from zope.interface import implements
from zope.schema.interfaces import IVocabularyFactory
from zope.schema.vocabulary import SimpleVocabulary

zope.app.schema 3.5.0 removes deprecated vocabulary directive.

2011/08/01

Transmogrifier Tips

SQLAlchemy: No module named exceptions

After running buildout, my Plone fails to start and show this message -- ImportError: No module named exceptions.
Adding a pin for SQLAlchemy to version 0.6.8 fixes the issue. For details see SQLAlchemy changelog

Named Transmogrifier Pipelines

In collective/transmogrifier/genericsetup.py, 'transmogrifier.txt' is assigned to be read. So place the file in profiles/default directory, pipeline identifiers are read one per line, for example 'mysite.migration.importFromCSV'. In ZMI portal_setup 'Import' tab, you can run the selected steps.

CSV Import with Transmogrifier

假設你的欄位資料,都放在 mydata.csv 檔案裡,想要批次匯入來建立 MyContentType 內容,下列是主要的步驟範例。

以自製模組 mysite.migration 為例,它的 configure.zcml 內容範例如下:
<configure
xmlns="http://namespaces.zope.org/zope"
xmlns:five="http://namespaces.zope.org/five"
xmlns:i18n="http://namespaces.zope.org/i18n"
xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
xmlns:transmogrifier="http://namespaces.plone.org/transmogrifier"
i18n_domain="mysite.migration">

<!-- Include zcml files of all required packages -->
<includeDependencies package="." />

<genericsetup:registerProfile
name="default"
title="mysite.migration"
directory="profiles/default"
description="MySite transmogrifier profile."
provides="Products.GenericSetup.interfaces.EXTENSION"
/>

<!-- Register Transmogrifier Profile -->
<include package="collective.transmogrifier" />
<include package="collective.transmogrifier" file="meta.zcml" />
<transmogrifier:registerConfig

name="mysite.migration.importFromCSV"
title="Import Content Data From CSV"
description="Transmogrifier config to import contents from CSV"
configuration="confs/import_from_csv.cfg"
/>

<!-- -*- extra stuff goes here -*- -->

</configure>

在 confs/import_from_csv.cfg 內容範例如下:
[transmogrifier]
pipeline =
csvsource
type-inserter
path-inserter
folders
constructor
schemaupdater
state-inserter
workflowupdater
reindexobject


[csvsource]
blueprint = collective.transmogrifier.sections.csvsource
filename = mysite.migration:data/mydata.csv

[type-inserter]
blueprint = collective.transmogrifier.sections.inserter
key = string:_type
value = string:MyContentType

[path-inserter]
blueprint = collective.transmogrifier.sections.inserter
key = string:_path
value = string:/myfolder/${item/id}

[folders]
blueprint = collective.transmogrifier.sections.folders

[constructor]
blueprint = collective.transmogrifier.sections.constructor

[schemaupdater]
blueprint = plone.app.transmogrifier.atschemaupdater

[state-inserter]
blueprint = collective.transmogrifier.sections.inserter
key = string:_transitions
value = string:publish

[workflowupdater]
blueprint = plone.app.transmogrifier.workflowupdater

[reindexobject]
blueprint = plone.app.transmogrifier.reindexobject

profiles/default/transmogrifier.txt 的內容範例如下:
# this file contains transmogrifier profile names to run
# on GenericSetup transmogrifier's step
mysite.migration.importFromCSV

以上模組檔案內容就緒後,在 buildout.cfg 加上:
[buildout]
...
develop =
src/mysite.migration

[instance]
...
eggs =
mysite.migration

執行 bin/buildout 之後,進入 ZMI 的 portal_setup 設定畫面,從 "Select Profile Or Snapshot" 下拉選單,點選 mysite.migration 項目,再點選 "Run transmogrifier pipeline" 項目,最後點選 "Import selected steps" 按鈕。