[3]ATContentTypesの拡張
ATContentTypesを拡張したコンテンツタイプの作成方法の基本です。
適切な基本的なパッケージ構造によって、content/ ディレクトリにほとんどの魔法があります。インポートしなくても???、content/richdocument.pyは文書とコメントのように振る舞います。それぞれの部分で行っていることを説明していきます。
最初にドキュメントのスキーマが定義されています。始めにATDocumentのスキーマをコピーします。コピーを作ることは重要です。あとでスキーマを編集るときにコピーをしていないと、注意深く標準のATDocumentのスキーマも編集しなければいけません。コピーを作成後、RichDocument用のフィールドを追加します。
RichDocumentSchema = ATDocument.schema.copy() + Schema((
BooleanField('displayImages',
default=False,
languageIndependent=1,
widget=ImagesManagerWidget(
description="If selected, a list of uploaded images will be "
"presented at the bottom of the document to allow "
"them to be easily downloaded.",
description_msgid='RichDocument_help_displayImages',
i18n_domain='RichDocument',
label="""Display images download box""",
label_msgid='RichDocument_label_displayImages',
),
),
BooleanField('displayAttachments',
default=True,
languageIndependent=1,
widget=AttachmentsManagerWidget(
description="If selected, a list of uploaded attachments will be "
"presented at the bottom of the document to allow "
"them to be easily downloaded",
description_msgid='RichDocument_help_displayAttachments',
i18n_domain='RichDocument',
label="""Display attachments download box""", label_msgid='RichDocument_label_displayAttachments',
),
),
),)
ImageManagerWidgetとAttachmentsManagerWidghetのカスタムウィジェット(wigdets/ フォルダにあります)を使うBooleanFieldsの使用方法は少しhackyです。画像と添付ファイルのアップロードと管理をするためコントロールを取得するためにRichDocumentはさらに複雑なウィジェットマクロをこれらのウィジェットに提供しています。booleanフィールドは画像と添付ファイルのダウンロードボックスをビューテンプレートの下部に表示するかを決めるために使用します。画像コントロールの残りの部分は、カスタムフォームコントローラを使って実装しています。このアクションは、Install.pyの中で標準の編集テンプレートをatct_editに登録します。
次に、スキーマの定義が終わったら、新しいスキーマでfinalizeATCTSchema()メソッドを呼び出します。これは、編集フォームの下に「関連文書」のリファレンスウィジェットが表示されるようになるなど、Ploneの標準的なフォーム形式に従うようになります。
finalizeATCTSchema(RichDocumentSchema)
適切にスキーマを定義したあとに、コンテンツクラスをとても簡単に定義します。このクラスはOrderedBaseFolderとATDocumentの両方を継承していいます。このため、RichDoumentはコンテナのように振る舞うことができます。OrderedBaseFolderを最初に継承しているので、ATDocumentとOrderedBaseFolder両方に定義されいているフィールドとメソッドは、RichDocumentではOrderedBaseFolderのフィールドとメソッドが利用されます
class RichDocument(OrderedBaseFolder, ATDocument):
"""
A document which may contain directly uploaded images and attachments
"""
# Standard content type setup
portal_type = meta_type = 'RichDocument'
archetype_name = 'Rich document'
content_icon = 'RichDocument.gif'
schema = RichDocumentSchema
typeDescription= 'A document which can contain rich text, images and attachments'
typeDescMsgId = 'RichDocument_description_edit'
画像と添付ファイルをRichDocumentに追加できるようにするために、これらは許可されたコンテンツタイプであることをArchetypesに宣言します。ImageAttachmentとFileAttachmentタイプの定義は、あとで説明します。
allowed_content_types = ['ImageAttachment', 'FileAttachment']
ATContentTypesはPlone2.1の表示メニューをフックする大抵の作業を行うことができます。このため、インスタンスごとにドキュメントの別のビューを選択できるようになります。詳細は動的ビューの選択で説明しますが、クラス定義の観点から見るとデフォルトビューを指定し、タイプをインストールする時に代替ビューを利用できるようにします。
default_view = 'richdocument_view'
immediate_view = 'richdocument_view'
suppl_views = ('richdocument_view_preview', 'richdocument_view_float')
Plone2.1は「ショートネーム」フィールドをデフォルトでは隠しています。ショートネームはIDをオブジェクトのタイトルから作成できます。この機能はArchetypesのレベルで実装されています。次にやることは、以下のことです。
_at_rename_after_creation = True
少し、反復処理が必要です。最初に、実装したインターフェースをZopeに指定します。ATDocumentからそれらを使用し、その中の二つを追加します。追加するのは、PloneのINonStructuralFolder(構造を持たないフォルダの章を参照)とinterfaces/richdocut.pyに定義されているIRichDocumentメーカーインターフェースです。
__implements__ = ATDocument.__implements__ + (IRichDocument, INonStructuralFolder,)
PloneとCMFのアクションは、リンクを定義する仕組です。「編集」などのビューにある緑色のタブはコンテンツタイプに定義されているアクションです。Plone2.1では、アクションは標準化されています。詳細は「アクションのエイリアス」の章を参照してください。標準のページ(ドキュメント)タイプと同じアクションを次のように定義します。:
actions = ATDocument.actions
ATDOcument(実際には、CMFDynamicViewFTIのBrowserDefaultMixinです。詳細は、「動的ビュー」の章を参照してください)のあるメソッドをオーバライドする必要があります。デフォルトでは、フォルダライクなオブジェクトはISelectableBrowserDefaultインターフェースによって「表示」メニューでデフォルトビューを定義できます。これは、ユーザにそのフォルダのデフォルトのページに使用するコンテンツのアイテムを選択できるようにします。RichDocumentではこの機能は意味がないので、次のようにして無効化します。
def canSetDefaultPage(self):
return False
最後にArchetypesにタイプを登録します。
registerType(RichDocument)
他のタイプの拡張
標準のPloneの画像やファイルタイプとは独立して画像と添付ファイルタイプのワークフローや他の機能を制御できるように簡単にImageAttachmentとFileAttachmentタイプを実装します。これらのタイプは、ATContentTypesと同等のタイプを単純に拡張したもので、タイプ名とドキュメンテーションを変更しているだけです。
これらのタイプは、content/attachments.pyに定義しています。
class FileAttachment(ATFile):
"""A file attachment"""
portal_type = meta_type = 'FileAttachment'
archetype_name = 'File attachment'
content_icon = 'file_icon.gif'
typeDescription= 'A file attached to a document'
typeDescMsgId = 'FileAttachment_description_edit'
global_allow = 0
default_view = 'fileattachment_view'
immediate_view = 'fileattachment_view'
suppl_views = ()
__implements__ = ATFile.__implements__
actions = ATFile.actions
registerType(FileAttachment)
class ImageAttachment(ATImage):
"""An image attachment"""
portal_type = meta_type = 'ImageAttachment'
archetype_name = 'Image attachment'
content_icon = 'image_icon.gif'
typeDescription= 'An image attached to a document'
typeDescMsgId = 'ImageAttachment_description_edit'
global_allow = 0
default_view = 'imageattachment_view'
immediate_view = 'imageattachment_view'
suppl_views = ()
__implements__ = ATImage.__implements__
actions = ATImage.actions
registerType(ImageAttachment)
これらのタイプのglobal_allowを無効にします。これは、RichDocumentの内部からだけ追加できるようにするためです。新たにクラスを作成せずにこれらのタイプを作成できます。単にATImageとATFile用にportal_typesにファクトリタイプ情報のアイテムをコピーして、すでに定義されている関連する情報を変更するだけです。新たなタイプを作成することは簡単で、自由に機能を追加できます。
mix-inクラスの使用
最後に、全てのタイプを拡張する必要があるかもしれません。ATContentTypesはmix-inクラスの中の一つの要素です。mix-inクラスでは独自のタイプを使用でき、コンテンツタイプの別のクラスの標準の設定とメソッドを使用できます。これらはATContentTypes/content/base.pyに定義されています。