Disable Products.TinyMCE URL Conversions

有時候,你會想輸入 /some_folder/some_item 這樣的網址,但 Products.TinyMCE 預設會雞婆地改成 ../some_folder/some_item 相對網址。想要取消這樣的行為,可以修改 Products.TinyMCE/skins/tinymce/tiny_mce_init.js 檔案,加上幾個設定值:

  fix_list_elements : false,
+ convert_urls: false,
+ relative_urls: false,
+ remove_script_host: false,
  // allow embed tag if user removes it from
  // list of nasty tags - see #10681
  media_strict: false


Plone on OpenShift

Here are some notes on setting up Plone instances on OpenShift based on https://github.com/kagesenshi/plone-openshift-quickstart documentation.

First, get your OpenShift client installed.

$sudo apt-get install git-core openssh-client ruby ruby-dev rubygems libopenssl-ruby
$ sudo su -
# gem install --source http://gems.rubyforge.org --source https://openshift.redhat.com/app/repo/ rhc


If this is your first time installing the RHC tools, please run 'rhc setup'


$ rhc app create -a openplone -t diy-0.1

Starting Interactive Setup for OpenShift's command line interface

It looks like you have not configured or used OpenShift client tools
on this computer. We'll help you configure the client tools with
a few quick questions. You can skip this in the future by copying
your configuration files to other machines you use to manage
your OpenShift account:


To connect to openshift.redhat.com enter your OpenShift login
(email or Red Hat login id): marr
Password: ********

Created local config file: /home/marr/.openshift/express.conf
The express.conf file contains user configuration,
and can be transferred to different computers.

We will now check to see if you have the necessary client tools installed.

Checking for git ... found

Checking for your namespace ... found namespace:

Checking for applications ... found
    * py - http://py-marr.rhcloud.com/

The OpenShift client tools have been configured on your computer.
You can run this setup wizard at any time by using the command
'rhc setup' We will now execute your original command
(rhc app create -a openplone -t diy-0.1)

Password: ********

Creating application: openplone in marr
Now your new domain name is being propagated worldwide
(this might take a minute)...
The authenticity of host 'openplone-marr.rhcloud.com ('
can't be established.
RSA key fingerprint is cf:ee:77:cb:0e:fc:02:d7:27:7e:ae:90:c0:90:88:a7.
Are you sure you want to continue connecting (yes/no)? yes
Enter passphrase for key '/home/marr/.ssh/id_rsa':
Checking if the application is available #1
Application openplone is available at: http://openplone-marr.rhcloud.com/
  Git URL: ssh://2abab67cb28b4684ab722d0064554394@
Disclaimer: This is an experimental cartridge that provides a way
to try unsupported languages, frameworks, and middleware on Openshift.

接著就進去新建的 openplone 目錄:

$ cd openplone
$ git remote add upstream -m master \
$ git pull -s recursive -X theirs upstream master
Enter passphrase for key '/home/marr/.ssh/id_rsa':
warning: no common commits
remote: Counting objects: 67, done.
remote: Compressing objects: 100% (47/47), done.
remote: Total 67 (delta 26), reused 59 (delta 18)
Unpacking objects: 100% (67/67), done.
From github.com:kagesenshi/plone-openshift-quickstart
 * branch            master     -> FETCH_HEAD
Auto-merging .openshift/action_hooks/stop
Auto-merging .openshift/action_hooks/start
Auto-merging .openshift/action_hooks/deploy
Auto-merging .openshift/action_hooks/build
Merge made by the 'recursive' strategy.
 .openshift/action_hooks/build  |    3 +-
 .openshift/action_hooks/deploy |   51 ++++++++++-
 .openshift/action_hooks/start  |   15 +++-
 .openshift/action_hooks/stop   |   14 +++-
 README.rst                     |   76 +++++++++++++++++
 bootstrap.py                   |  181 ++++++++++++++++++++++++++++++++++++++++
 buildout.cfg                   |   40 +++++++++
 7 files changed, 371 insertions(+), 9 deletions(-)
 create mode 100644 README.rst
 create mode 100644 bootstrap.py
 create mode 100644 buildout.cfg

檢查 domain 的話,會看到所有的 app 資訊:

$ rhc domain
Password: ********

Applications in marr:

py @ http://py-marr.rhcloud.com/
Created: 2:08 AM
Git URL:


openplone @ http://openplone-marr.rhcloud.com/
Created: 2:38 AM
Git URL:


.git/config 內容長得像這樣,為了版面,我用了 \ 符號:

        repositoryformatversion = 0
        filemode = true
        bare = false
        logallrefupdates = true
[remote "origin"]
        url = ssh://2abab67cb28b4684ab722d0064554394@ \
        fetch = +refs/heads/*:refs/remotes/upstream/*
[branch "master"]
        remote = origin
        merge = refs/heads/master

執行 git push 後,buildout 就會執行,這會花一段時間,我跑了至少 40分鐘。

$ git push
remote: ~/git/openplone.git
remote: Starting application...
remote: . . . . . . . . . . .
remote: daemon manager not running
remote: Done
remote: Running .openshift/action_hooks/post_deploy

打開瀏覽器,在 http://openplone-marr.rhcloud.com/ 看得到起始畫面。利用 ssh 也看得到檔案系統。

$ ssh 2abab67cb28b4684ab722d0064554394@openplone-marr.rhcloud.com "ls -l app-root/data/filestorage"

設定 Virtual Hosting 的資訊:

$ rhc app add-alias -a openplone --alias plone.mydomain.org
Password: ********


$ rhc-port-forward -a openplone
Warning: This command is deprecated and will be removed in the future. Please use 'rhc port-forward' instead.

Password: ********

Checking available ports...
Enter passphrase for /home/marr/.ssh/id_rsa:

Binding python ->
Enter passphrase for /home/marr/.ssh/id_rsa:
Use ctl + c to stop

Error trying to forward ports. You can try to forward manually by running:

ssh -N -L 2abab67cb28b4684ab722d0064554394@openplone-marr.rhcloud.com

再設定 DNS entry 和 ZMI 裡的 VHM 就行了:


PyHUG September Seminar

PyHUG 九月17日的活動很成功,電腦教室塞滿人,學習和交流的氣氛也很熱烈。

感謝很多人的幫忙,讓我有機會講了 Plone - Evolving Python CMS 題目,在聽眾的回應裡,我覺得 ZODB vs Relational DB 和 Javascript Form Builder (例 backbone-form ) 值得日後繼續探討。沒試過的東西,一般人總是不容易想像,如果學習門檻能夠降低,讓人多些機會做中學,這樣的學習效果才容易提高。

最後,台北地區的朋友,想要感受現場交流的氣氛,最簡單的方法當然就是參加 Taipei.py 活動囉。


SQL Integration to Plone

SQL 是一個成熟的世界,即使 ZODB or SQL 是個討論議題,實務上還是要想辦法讓它們互通有無。整合的方法主要有三大類:

  1. Database Adapter + Z SQL Method
  2. 這是傳統方法,先安裝 Database Adapter 再用 ZSQL Method 建立存取邏輯的程式碼,最後由 Page Template 建立操作和顯示的介面。整個流程邏輯跟 PHP / ASP 早期硬幹應用程式很像,原則上就是按照 CRUD 概念去刻。常見的 MySQL 可以搭 zmysqlda,PostgreSQL 可以搭 psycopg2,更多細節可參照範例文件

  3. ORM (SQLAlchemy)
  4. 在 Database Adapter 的基礎上,還可以利用 Object Relation Mapper (ORM) 來協助開發,像 SQLAlchemy 就是一個 ORM 工具,越來越多 SQL 整合是透過它來進行,成熟的例子之一是 ContentMirror,它把 ZODB 的內容資料同步儲存在 SQL 資料庫裡,目前支援 Archetypes 的型別內容,據說傳到 Google App Engine 沒有問題,還沒機會實測。

  5. Pickle
  6. 另一種思惟方式,是直接把 Pickle 資料塞到 SQL 資料庫裡,像 RelStorage 就是這類例子。


portal_setup Import Steps

Importing steps of base profile by mistake, will be a disaster for the Plone site. At least I run into it twice. For example, a message like this might appear in log file:

TypeError: unhashable type: 'Missing.Value'

The webpage output simply keeps showing errors. What I do wrong is to import the Catalog Tool step of base profile, that ends up cleaning all the indexes in portal_catalog. Indexes such as Creator, Date, Description are there, but # distrinct values are 0. Luckily, after clicking Updated Catalog in Advanced tab, and the Plone site comes live again.