2012/08/30

Essential ArcPy Vocabulary

ArcPy site-package 搭在 Python 2.6 版本之上,它有幾個重要的模組、類別、函式,像是:

  • mapping module (arcpy.mapping)
  • Spatial Analyst module (arcpy.sa)
  • Geostatistical Analyst module (arcpy.ga)
  • SpatialReference class
  • Extent class
  • ListFeatureClasses()

技術層面來看,tool 和 function 有所區別,前者會回傳 result 物件或產生 message,後者不會這樣做,另一方面,tool 會依 product (ArcView, ArcEditor, ArcInfo) 或 extension (Network Analyst, Spatial Analyst) 來授權使用,function 則是直接安裝在 ArcPy 裡。

設定 workspace 時,路徑寫法如下,用 "C:\data\my_folder" 可能會有問題:

>>> arcpy.env.workspace = "C:/data/my_folder"

在 geodatabase 裡建立 feature class 時,需要指定 feature class 的類別 (point, line, polygon, etc)。

Removing PasteScript Dependency

看到消息說沒人想解決 PasteScript / PasteDeploy 的臭虫,之前相依的軟體,也可能連帶造成問題,開始思考要跳船,像 Cheetah 就可能被 Jinja2 取代。

究竟這三個人到底是命運的安排,還是情感的糾結,抑或是另有隱情,真相到底是什麼,讓我們繼續看下去。

2012/08/28

ftw.meeting Reviewed

ftw.meeting 是一個 Archetypes 模組,功能跟 Event 類似,不過設計成 folderish 因此可以包含 Meeting Item,搭配 ftw.pdfgenerator 還可以匯出 PDF 檔案。

安裝時的相依模組,主要包括 Products.DataGridField、ftw.calendarwidget。

它使用 ftw.calendarwidget 作為月曆輸入介面,特色是整合了 jQuery UI calendar widget。

在 Event type 欄位選擇 Meeting 項目的話,會在下方即時展開 Meeting form 等四個欄位,它們都指定為 schemata='meeting'。

DataGridField 用於動態新增與會名單,不過實際用到的程式碼有新增 select all 功能,細節可參考 content/widget.py 檔案的 DataGridWidgetExtended 類別內容。

網站新增會員帳號後,就可以成為與會人員的選項。

程式碼範例片段如下:

atapi.StringField(
    name='meeting_type',
    searchable=False,
    schemata='default',
    required=True,
    default='event',
    vocabulary_factory='ftw.meeting.types',

    widget=atapi.SelectionWidget(
        label=_(u"meeting_label_type", default=u"Event type"),
        description=_(u"meeting_help_type",
                      default=u"Choose your event type."),
        helper_js=['meeting_toggle_date.js', ],
        format='radio')),

DataGridField(
    name='responsibility',
    searchable=False,
    schemata='default',
    columns=('contact', ),
    allow_empty_rows=False,

    widget=DataGridWidgetExtended(
        label=_(u"meeting_label_responsibility",
                default=u"Responsibility"),
        description=_(
            u"meeting_help_responsibility",
            default=u"Enter the responsible of the meeting."),
        auto_insert=True,
        select_all_column='contact',
        columns={
            'contact':
                SelectColumn(
                title=_(
                    u"meeting_label_responsibility",
                    default="Responsibility"),
                vocabulary='getAttendeesVocabulary'
                ),
            })),

DataGridField(
    name='attendees',
    searchable=True,
    schemata='meeting',
    columns=('contact', 'present'),
    allow_empty_rows=False,

    widget=DataGridWidgetExtended(
        label=_(u"meeting_label_attendees",
                default=u"Attendees"),
        description=_(u"meeting_help_attendees",
                      default=u"Enter the attendees of the meeting."),
        auto_insert=True,
        select_all_column='contact',

        columns={
            'contact': SelectColumn(
                title=_(
                    u"meeting_label_attendees_attendee",
                    default=u"Attendee"),
                vocabulary='getAttendeesVocabulary'
                ),
            'present': SelectColumn(
                title=_(
                    u"meeting_label_attendees_present",
                    default=u"Present"),
                vocabulary='getPresentOptions',
                ),
            })),

ZODB 裡的儲存範例如下:

>>> app.mysite['my-meeting'].responsibility
({'contact': 'ababy'}, {'contact': 'jsmith'})

>>> app.mysite['my-meeting'].attendees
({'contact': 'ababy', 'present': 'present'},
 {'contact': 'jsmith', 'present': 'excused'})

在顯示上,實作了 Drag and Drop Order 功能,可以即時拖拉來決定 Meeting Item 的順序,它會更新 getObjPositionInParent 的索引值。

點選各別的 Meeting Item 則會展開更多欄位資訊。

2012/08/22

Path Listing Script

Plone 網站使用 /TaipeiCity/nangang 之類的路徑,來表示行政地區資訊,下列程式碼可以列出清單:

for k,v in context.objectItems():
    if v.meta_type == 'ATFolder':
        print k, v.Title()
        for x,y in v.objectItems():
            if y.meta_type == 'ATFolder':
                print k+'/'+x, y.Title()
return printed

2012/08/13

Dexterity QuickStart

透過 ZopeSkel 可以協助客製 Archetype 程式碼,同樣的原理方法也適用於 Dexterity,搭配 Plone 4.2 Unified Installer 的話,只需要在 base.cfg [zopeskel] section 加上 zopeskel.dexterity

[zopeskel]
# installs paster and Zopeskel
recipe = zc.recipe.egg
eggs =
    ZopeSkel
    Paste
    PasteDeploy
    PasteScript
    zopeskel.dexterity
    ${buildout:eggs}

再執行 bin/buildout 就能在 src 目錄裡用 ../bin/zopeskel dexterity 來建立骨架程式碼。

典型的 Dexterity 程式碼,__init__.py 的主要功能是設定 i18n message factory,內容類似如下:

from zope.i18nmessageid import MessageFactory

# Set up the i18n message factory for our package
MessageFactory = MessageFactory('tws.dxcontent')

接著,重頭戲是從下列的 mytype.py 內容開始。在 zope.schema 找得到標準欄位的定義,除此之外,通常也會用到 plone.app.textfield 和 z3c.relationfield 這兩個模組:

from five import grok
from plone.directives import dexterity, form

from zope import schema
from zope.schema.interfaces import IContextSourceBinder
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm

from zope.interface import invariant, Invalid

from z3c.form import group, field

from plone.namedfile.interfaces import IImageScaleTraversable
from plone.namedfile.field import NamedImage, NamedFile
from plone.namedfile.field import NamedBlobImage, NamedBlobFile

from plone.app.textfield import RichText

from z3c.relationfield.schema import RelationList, RelationChoice
from plone.formwidget.contenttree import ObjPathSourceBinder

from myproj.dxcontent import MyTypeMessageFactory as _

註:ObjPathSourceBinder 之前出現在 z3c.relationfield.schema 裡面,新的版本出現在 plone.formwidget.contenttree 裡。另外,也明確可以看到 schema-defined interface 和 model-based interface 兩種設定方式。

如果要用到 validator,下列是個例子:

def codeIsValid(value):
    """Contraint function to make sure the given code is valid
    """
    if value:
        if len(value) < 4 or len(value) > 6 or \
            not value.startswith('C'):
        raise Invalid(
            _(u"The code is not of the correct format")
        )
    return True

透過網頁可以管理設定這些型別:

點選 Export Schema Models 按鈕,可以儲存 dexterity_models-20120801030127.zip 內含 models/*.xml 檔案,點選 Export Type Profiles 按鈕,可以儲存 dexterity_export-20120801031015.zip 內含 types.xml 和 types 目錄。

不過,網頁式的 Model 設定結果,如果使用中文的話,長得像這樣:

<field name="text" type="plone.app.textfield.RichText">
     <description />
     <title>內文</title>

2012/08/09

PDF Preview in Plone

之前試過 wc.pageturner 模組,缺點就是要加裝 SWFTools 工具,最近再試了 collective.pdfpeek,遇到 TypeError,這錯誤如果早在 Plone 4.0.2 時代就存在,那 Plone 4.2.x 跑不動也就不足為奇。

既有的結論是,在沒有更好模組出來前,必要時就用 wc.pageturner 吧。

編譯步驟:

  • wget http://www.swftools.org/swftools-0.9.2.tar.gz
  • tar zxvf swftools-0.9.2.tar.gz
  • cd swftools-0.9.2/
  • apt-get install libgif-dev
  • LDFLAGS=-lstdc++ ./configure
  • make
  • make install