透過ZMI網頁介面進行Plone網站設定,並了解GenericSetup基本原理後,接著使用Paste工具建立網站專案。首先,探討需求分析,然後使用paster建立模組、建構模組目錄結構、註冊Extension Profile,並建立自製型別。
前篇文章介紹了Plone的內部管理工具,講解透過ZMI的網頁介面進行網站設定的方法,也說明了GenericSetup的基本原理。有了這些知識和練習,在檔案系統上撰寫客製化的程式碼,也就更容易上手。
Plone使用一個稱為Paste的工具,協助開發人員建立網站專案Paste提供一系列的中介軟體和工具程式,透過WSGI標準介面來讓應用程式溝通,其中包括一個稱為PasteScript的模組,內含paster工具程式,可以用來建立模組軟體的骨架程式碼,並以egg檔案格式儲存Paste,以及單獨執行測試工作,不需要跟Server程式綁在一起,目前廣泛被Python程式人員用於專案建置的場合。
在本文中要模擬一個專案,專案的目標是建立一個網站,能夠新增活動資訊,並接受報名資料。我們將認識模組的命名空間,在檔案系統上,利用paster建立擴充模組的骨架,調整程式碼及設定值,以滿足上述的專案需求。
需求分析
從內容管理的角度來分析,專案裡要處理的資料,將被規劃成內容型別,例如活動資訊是具備Folder特性的Event型別,稱之為Event Folder,它能夠包含稱為Signup的報名資料,這樣的設計可以實作1對N的關係,也就是1個Event Folder包括N個Signup型別。
減少重造輪子,則是另一個重要原則,實作時善用既有的功能或模組,是聰明的方式。Plone預設提供Event型別,可以作為Event Folder模仿的基礎,再把Signup型別搞定,主要的內容型別都自製完成。
上述的設計,可以利用Archetypes框架來實作,而且paster工具程式能協助簡化整個過程。不過,設計與實作的方式存在多種方案,將試著先從最簡化的方案開始練習。
使用paster建立模組
實際使用paster的時候,通常要搭配template才方便,例如Plone的場合搭配ZopeSkel的template,使用Unified Installer的話,已經完成ZopeSkel的安裝,執行「paster create --list-templates」指令,可以列出既有支援的template項目,如圖1所示。
|
▲圖1 paster所支援的template列表。 |
我們需要的是Archetypes框架的template,所以執行「paster create -t archetype」指令,後面再接模組的名稱,也就是mysite.eventfolder,名稱前面的mysite是命名空間,如圖2所示。
|
▲圖2 paster建立Archetypes專案。 |
paster會顯示一些問題,多數以預設值回答就行,通常直接按下〔Enter〕按鍵代表使用預設值,如圖3所示。
|
▲圖3 Archetypes專案建立時的預設問題。 |
一切順利的話,模組的egg資訊就建立完成,最後的畫面並提示有一個addcontent的Local Command可以使用,如圖4所示。
|
▲圖4 Archetypes專案建立後的畫面。 |
接著,編輯buildout.cfg檔案,分別在eggs與zcml的變數,指定「mysite.eventfolder」變數值,develop變數則指定「src/mysite.eventfolder」,如圖5所示。
|
▲圖5 編輯buildout.cfg的部分參數值。 |
由於處於模組開發階段,建議將debug-mode變數值指定為「on」,在系統日誌檔裡,就會記錄更多有助於除錯的資訊,如圖6所示。
|
▲圖6 編輯buildout.cfg的debug-mode參數值。 |
儲存buildout.cfg檔案後,要執行「bin/buildout」指令讓設定值生效,由於既有的自製模組並沒有牽涉到網路上的資源,因此可以使用Off Line模式,也就是-o參數,來加速buildout的過程,如圖7所示。
|
▲圖7 執行buildout,讓設定值生效。 |
模組目錄結構說明
現在,系統已經能夠認得我們的新模組,執行「bin/zopepy」指令載入模組名稱。
若沒有出現ImportError的話,表示Zope instance已經能夠使用模組了,如圖8所示。按〔Ctrl〕+〔D〕組合鍵離開zopepy的執行。
|
▲圖8 執行zopepy指令的畫面。 |
傳統的Zope 2應用程式,只要把程式專案放進「$INSTANCE_HOME/Products」目錄,Zope就會在啟動時掃描這個目錄,並處理應用程式的安裝與註冊工作。
這樣便利的方式有其缺點,一方面,搭配Products.*命名空間的黑魔法,只能被Zope系統認得,很難再應用於其他場合,另一方面,也造成命名空間的侷限,開發者不容易建立精簡而重用性高的模組。
Plone在第2版與第3版之間,擴充模組的命名方式開始有所不同,Plone 2常見的範例類似PloneSurvey或WebServerAuth,但Plone 3常見的範例則像是Products.Maps、plonetheme.stylized或collective.indexing。這裡自製的模組名稱便使用mysite的命名空間,再加上eventfolder的名稱。
名稱之間以「.」符號隔開,在檔案系統裡,預設則以「/」符號及目錄架構來隔開。第一層的目錄裡,包括模組egg或README.txt之類的基本資訊,在mysite目錄裡,則包含第二層的eventfolder目錄,這裡才是實作細節的所在,如圖9所示。
|
▲圖9 mysite.eventfolder的目錄結構。 |
自製模組執行buildout生效後,會向系統註冊一個development egg,讓系統能夠啟用它,並在「etc/package-includes」目錄裡,建立一個ZCML設定檔,這樣的設定檔稱為slug,內容範例如下:
此時啟動Plone的話,到Site Setup前台管理介面,在「Add-ons」裡會看得到這個新模組,如圖10所示。不過,現在並不急著啟用它,因為還需要修改程式碼。
|
圖10 Add-ons裡顯示模組的畫面。 |
設定Extension Profile
之前提過,Plone所搭配的GenericSetup,使用到base profile和extenstion profile兩種設定方式。自製模組的場合,通常是註冊extension profile,當Zope啟動時,會經由ZCML slug來通知系統讀取新的設定值。
在此處的範例裡,檔案mysite.eventfolder/mysite/eventfolder/configure.zcml使用provides設定值,genericsetup:registerProfile裡,註冊了extension profile,它的名稱是「default」,對應一個「profiles/default」目錄,它的標題是Event Folder,如圖11所示。
|
▲圖11 mysite/eventfolder/configure.zcml內容。 |
profile的完整名稱包括了模組名稱,也就是使用mysite.eventfolder:default形式,如果要在同一個模組裡註冊多個extension profile,就必須使用不同的名稱和目錄。
在「profiles/default」目錄裡,看得到一些XML檔案,它們是GenericSetup執行時所讀取的設定內容。以types.xml為例,這個檔案用來註冊portal_types裡的新型別資訊。
為了新增需要的內容型別,要在模組目錄裡繼續執行paster的指令,特別是利用ZopeSkel的addcontent local command,如圖12所示。
|
▲圖12 addcontent的local command訊息。 |
同樣地,addcontent支援多種template項目,稍後要用的是contenttype和atschema,如圖13所示。
|
▲圖13 addcontent所支援的template列表。 |
建立自製型別
建立自製型別的過程,可以分成content type和schema兩個階段。
執行「paster addcontent contenttype」之後,同樣會顯示出一些問題,由於Event Folder被規劃成folderish特性,這項問題記得要指定True設定值,如圖14所示。
|
▲圖14 addcontent contenttype執行畫面。 |
如果執行過程中選項弄錯了,可以按〔Ctrl〕+〔C〕組合鍵強迫中斷,重頭再來一次。
接著,執行「paster addcontent atschema」指令。請事先閱讀Archetypes的field和widget說明文件,以確保能夠選用最合適的欄位類型。
|
▲圖15 addcontent atschema執行畫面。 |
首先,要決定content class的檔案名稱,這個範例裡設定的是eventfolder,在檔案系統裡,它會以eventfolder.py檔名出現。
然後,依序決定field的各項屬性值。在此範例裡,以startDate為名稱,指定它為datetime型別,其餘使用預設值,如圖16所示。
|
▲圖16 field設定畫面。 |
paster已經幫忙建立好第一個field的骨架程式碼,如果想要建立第二個field的屬性值,可以重複上述的「addcontent atschema」指令,當然,也可以直接手動編輯Python原始檔,仿照骨架程式碼的內容,依樣畫葫蘆。
如果急著想看看結果,執行「bin/plonectl fg」指令,以便除錯訊息能在前景顯示,如圖17所示。
|
▲圖17 plonectl fg執行畫面。 |
若一切順利的話,在Plone裡已經可以從新增項目的下拉選單中找到剛剛自製的內容型別,而且任一目錄裡都能執行新增動作,如圖18所示。
|
▲圖18 新增項目裡找得到Event Folder。 |
新增Event Folder的時候,除了既有的Title和Description欄位之外,編輯畫面也會顯示剛才建立的Event Starts欄位,如圖19所示。
|
▲圖19 Event Folder的編輯畫面。 |
結語
我們開始模擬一個小型專案,從需求分析開始,尋找合適的工具,修改系統成為想要的樣子,就像組合樂高積木一般。
如果把paster建立骨架程式碼的過程,以及詳細記錄目錄檔案的資訊進行比對,就可以觀察模組開發的成長歷程。
以mysite.eventfolder的Archetypes專案為例,系統透過「mysite/eventfolder/configure.zcml」檔案來註冊extension profile,在「interfaces」目錄裡註冊IEventFolder介面檔案,其中的I代表interface之意,如圖20所示。interface是Zope 3所導入的新設計概念,日後還會介紹它。
|
▲圖20 interfaces/eventfolder.py檔案內容。 |
在content目錄裡,同樣有一個configure.zcml檔案,這個檔案是用來指定content component的設定值,包括它的介面檔案位置,以及實作class的程式碼位置。「.eventfolder」代表content目錄裡的eventfolder檔案或目錄,而「..interfaces」代表content上一層目錄的interfaces檔案或目錄,如圖21所示。
|
▲圖21 content/configure.zcml檔案內容。 |
本文還沒開始新增Signup內容型別,不過它的建立原理與Event Folder大同小異,另外,我們也將探究程式碼的細節,以便修改模組,滿足專案實際的需求,這些都待下回分曉。