2011/09/22

Transmogrifier in Action

最近用 collective.transmogrifier 將資料匯入 Plone 4.0.7,同時支援 CSV 和 PostgreSQL 兩種來源格式。

首先,用 paster 建立一個 my.importer 的專案,其中的 configure.zcml 內容範例如下:
<configure
    xmlns="http://namespaces.zope.org/zope"
    xmlns:five="http://namespaces.zope.org/five"
    xmlns:genericsetup="http://namespaces.zope.org/genericsetup"
    xmlns:transmogrifier="http://namespaces.plone.org/transmogrifier">

  <includeDependencies package="." />

  <genericsetup:registerProfile
      name="default"
      title="my.importer"
      directory="profiles/default"
      description="To set context for transmogrifier profiles."
      provides="Products.GenericSetup.interfaces.EXTENSION"
      />

  <include package="collective.transmogrifier" />
  <include package="collective.transmogrifier" file="meta.zcml" />
  <transmogrifier:registerConfig
    name="my.importer.importMyNews"
    title="My Importer for MyNews"
    description="Transmogrifier Pipeline config to import contents."
    configuration="confs/import_mynews.cfg"
    />

</configure>
在 confs 目錄裡,我們編輯 import_mynews.cfg 設定檔,範例內容如下:
[transmogrifier]
pipeline =
#    csvsource
    sqlsource
    type-inserter
    path-inserter
    folders
    constructor
    schemaupdater
    state-inserter
    workflowupdater
    reindexobject

#[csvsource]
#blueprint = collective.transmogrifier.sections.csvsource
#filename = my.importer:data/mynews.csv

[sqlsource]
blueprint = transmogrify.sqlalchemy
dsn = postgresql://username:secret@localhost:5432/dbname
query = SELECT id, title, description FROM my_table

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

[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
來源是 SQL 資料時,使用的是 [sqlsource],來源是 CSV 資料時,就改用 csvsource,並在 data 目錄裡放好 mynews.csv 檔案,內容範例如下:
id,title,description
data1,My Data #1,Description of My Data #1
接著,編輯 my/importer/profiles/default/transmogrifier.txt 檔案,內容如下:
# this file contains transmogrifier profile names to run
# on GenericSetup transmogirifier's step
my.importer.importMyNews
以上就是 my.importer 專案的主要設定內容。最後,編輯 buildout.cfg 的內容如下:
eggs =
     SQLAlchemy == 0.6.5
    psycopg2
    collective.transmogrifier
    plone.app.transmogrifier
    transmogrify.sqlalchemy
   my.importer

zcml =
    collective.transmogrifier-meta
    collective.transmogrifier
    plone.app.transmogrifier
    transmogrify.sqlalchemy
上述 SQLAlchemy == 0.6.5 語法,代表要指定 (pin) 安裝 0.6.5 版本的 SQLAlchemy,不指定的話,可能會安裝太新的版本,未必合用,我的經驗是 SQLAlchemy 0.7.2 會遇到 ImportError: No module named exceptions 錯誤訊息。

一切搞定後,要讓上述設定值生效的話,可以直接到 ZMI 的 portal_setup,在 Import 頁籤裡,從 Select Profile or Snapshot 找尋 my.importer 選項,再找到 Run transmogrifier pipeline (第41項) 並勾選它,最後點選 Import selected steps 按鈕。

額外一提,PostgreSQL 裡的欄位資料如果更新為空值,執行 transmogrifier 後,也會將 Plone 表單欄位清空。

No comments: