2012/03/05

First Step with Git

許多 Plone Collective 程式碼都從 subversion 搬到 git 了,今天拿 Products.AutocompleteWidget 當例子,記錄操作過程:

$ cd src
$ git clone https://github.com/collective/Products.AutocompleteWidget.git
Cloning into Products.AutocompleteWidget...
remote: Counting objects: 217, done.
remote: Compressing objects: 100% (107/107), done.
remote: Total 217 (delta 88), reused 215 (delta 86)
Receiving objects: 100% (217/217), 50.84 KiB, done.
Resolving deltas: 100% (88/88), done.

$ cd Products.AutocompleteWidget
$ git status
# On branch master
nothing to commit (working directory clean)

不過,比對程式碼之後,發現最新版本的內容,還是源自於 subversion,目前 1.4.0 是以 http://svn.plone.org/svn/archetypes/MoreFieldsAndWidgets/Products.AutocompleteWidget/branches/improved_multivalued_fields_management 為基礎。

2012/03/01

Script to List Items

不需要建立模組,在 ZMI 新增 Python Script 就能在 Plone 環境執行簡單的查詢工作,例如顯示 News Item 的基本欄位資料。

from Products.CMFCore.utils import getToolByName

request = container.REQUEST
catalog = getToolByName(context, 'portal_catalog')
path = '/mysite/news'

for brain in catalog(portal_type='News Item', path=path):
    try:
        obj = brain.getObject()
        print "%s, %s, %s, %s" % \
              (brain.getPath(), obj.Title(), obj.Contributors()[0], obj.EffectiveDate())
    except:
        pass
return printed

上述執行結果,是方便另存成 CSV 檔案格式。

from Products.CMFCore.utils import getToolByName

catalog = getToolByName(context, 'portal_catalog')
areas = ['TaipeiCity', 'NewTaipeiCity']
path = '/mysite/myfolder'

for i in areas:
    brains = catalog(portal_type='Image', path=path+'/'+i)
    print "%s: %d" % (i, len(brains))
print "Total: %d" % len(catalog(portal_type='Image', path=path))

return printed

2012/02/24

Version Conflict While Running Buildout

安裝的模組如果使用 z3c.form,在 Plone 4.1 以下的環境,很容易遇到 版本衝突的訊息

While:
  Installing instance.
Error: There is a version conflict.
We already have: zope.schema 3.5.4
but z3c.form 2.6.1 requires 'zope.schema>=3.6.0'.

詳細的處理方式是,如果找得到 versions.cfg 檔案,就在裡面加上 z3c.form = 2.2.0 的設定,如果沒有 versions.cfg 檔案,就是寫在 buildout.cfg 檔案裡,再把之前被裝進系統的 z3c.form 刪除,例如 buildout-cache/eggs/z3c.form-2.6.1-py2.6.egg。在 z3c.form 2.3.0 用到 zope.schema 3.6.0,造成相容性的大調整。

2012/02/22

Embed Tile

以前在 Plone 要嵌入 Gmap 的步驟並不直覺,現在有機會變得簡單了。toutpt 正在開發的 collective.oembedtile 讓你直接編輯 Gmap 或 Youtube 的嵌入碼。

2012/02/15

Display Only For Logged In Users

除了讓未登入的訪客看得到會員清單之外,常見的需求,就是限制特定欄位,僅允許登入的使用者才看得到。下列是程式碼範例:

<tal:block define="isAnon context/@@plone_portal_state/anonymous">
<span tal:condition="python: not isAnon"
      tal:replace="context/content_to_show" />
</tal:block>

控制 navigation tab 的顯示,是另一個常見的需求,這要在 portal_actions/portal_tabs 裡設定 Condition (Expression),常見的例子是 python:(member is not None),控制登入的使用者才看得到 tab。

更多常見的權限定義,像是 'Manage portal' 或 'View',被稱為 CMF Core Permission,可以先到 Products/CMFCore/permissions.py 檔案裡找。

2012/02/04

Products.AutocompleteWidget Sample

Products.AutocompleWidget 有支援 Plone 4.x,範例程式碼並不多,因此特別記錄找到的:

測試結果,使用 multiValued=True 後,編輯介面才看得到變化。

"""Definition of the Wiki Doc content type
"""

from zope.interface import implements, directlyProvides

from Products.Archetypes import atapi
from Products.Archetypes.public import LinesField
from Products.Archetypes.public import DisplayList
from Products.ATContentTypes.content import base
from Products.ATContentTypes.content import schemata
from Products.AutocompleteWidget.AutocompleteWidget import AutocompleteWidget
from Products.CMFCore.utils import getToolByName


from tlc.kbase import kbaseMessageFactory as _
from tlc.kbase.interfaces import IWikiDoc
from tlc.kbase.config import PROJECTNAME

WikiDocSchema = schemata.ATContentTypeSchema.copy() + atapi.Schema((

          
     LinesField('tags',
                searchable=1,
                required=0,
                mutator='setTagSubject',
                accessor='getTagSubject',
                edit_accessor='getTagSubject',
                vocabulary='getSubjectVocab',
                widget=AutocompleteWidget(label='Tags'),
                enforceVocabulary=0,
     ),

))

# Set storage on fields copied from ATContentTypeSchema, making sure
# they work well with the python bridge properties.

WikiDocSchema['title'].storage = atapi.AnnotationStorage()
WikiDocSchema['description'].storage = atapi.AnnotationStorage()

schemata.finalizeATCTSchema(WikiDocSchema, moveDiscussion=False)

class WikiDoc(base.ATCTContent):
    """Description of the Example Type"""
    implements(IWikiDoc)

    meta_type = "Wiki Doc"
    schema = WikiDocSchema

    title = atapi.ATFieldProperty('title')
    description = atapi.ATFieldProperty('description')
    
    def setTagSubject(self, value):
        """Set tag widget contents to subject of object"""
        self.getField('subject').set(self, value)
 
    def getTagSubject(self):
        """Set tag widget contents to subject of object"""
        return self.Subject()
 
    def getSubjectVocab(self):
        """Get subject (keywords) vocabulary"""
        catalog = getToolByName(self, 'portal_catalog')
        return catalog.uniqueValuesFor('Subject')

atapi.registerType(WikiDoc, PROJECTNAME)