4.2 SchemaとFTI
Schemaを書きます。
example.conference/example/conference/__init__.py
from zope.i18nmessageid import MessageFactory _ = MessageFactory("example.conference")
example.conference/example/conference/presenter.py
from five import grok from zope import schema from plone.directives import form, dexterity from plone.app.textfield import RichText from plone.namedfile.field import NamedImage from example.conference import _ class IPresenter(form.Schema): """A conference presenter. Presenters can be added anywhere. """ title = schema.TextLine( title=_(u"Name"), ) description = schema.Text( title=_(u"A short summary"), ) bio = RichText( title=_(u"Bio"), required=False ) picture = NamedImage( title=_(u"Picture"), description=_(u"Please upload an image"), required=False, )
example.conference/example/conference/program.py
from five import grok from zope import schema from plone.directives import form, dexterity from plone.app.textfield import RichText from example.conference import _ class IProgram(form.Schema): """A conference program. Programs can contain Sessions. """ title = schema.TextLine( title=_(u"Program name"), ) description = schema.Text( title=_(u"Program summary"), ) start = schema.Datetime( title=_(u"Start date"), required=False, ) end = schema.Datetime( title=_(u"End date"), required=False, ) details = RichText( title=_(u"Details"), description=_(u"Details about the program"), required=False, )
example.conference/example/conference/session.py
サンプルはMessageFactoryのインポートが抜けているので書き足します。
from five import grok from zope import schema from plone.directives import form, dexterity from plone.app.textfield import RichText from example.conference import _ class ISession(form.Schema): """A conference session. Sessions are managed inside Programs. """ title = schema.TextLine( title=_(u"Title"), description=_(u"Session title"), ) description = schema.Text( title=_(u"Session summary"), ) details = RichText( title=_(u"Session details"), required=False )
FTI(Factory Type Information)を書きます。
example.conference/example/conference/profiles/default/types.xml
<object name="portal_types"> <object name="example.conference.presenter" meta_type="Dexterity FTI" /> <object name="example.conference.program" meta_type="Dexterity FTI" /> <object name="example.conference.session" meta_type="Dexterity FTI" /> </object>
example.conference/example/conference/profiles/default/typesというディレクトリを作成して、ファイルを追加します。
example.conference/example/conference/profiles/default/types/example.conference.presenter.xml
<?xml version="1.0"?> <object name="example.conference.presenter" meta_type="Dexterity FTI" i18n:domain="example.conference" xmlns:i18n="http://xml.zope.org/namespaces/i18n"> <!-- Basic metadata --> <property name="title" i18n:translate="">Presenter</property> <property name="description" i18n:translate="">A person presenting sessions</property> <property name="content_icon">user.gif</property> <property name="allow_discussion">True</property> <property name="global_allow">True</property> <property name="filter_content_types">True</property> <property name="allowed_content_types" /> <!-- schema interface --> <property name="schema">example.conference.presenter.IPresenter</property> <!-- class used for content items --> <property name="klass">plone.dexterity.content.Item</property> <!-- add permission --> <property name="add_permission">cmf.AddPortalContent</property> <!-- enabled behaviors --> <property name="behaviors"> <element value="plone.app.content.interfaces.INameFromTitle" /> </property> <!-- View information --> <property name="default_view">view</property> <property name="default_view_fallback">False</property> <property name="view_methods"> <element value="view"/> </property> <!-- Method aliases --> <alias from="(Default)" to="(dynamic view)"/> <alias from="edit" to="@@edit"/> <alias from="sharing" to="@@sharing"/> <alias from="view" to="(selected layout)"/> <!-- Actions --> <action title="View" action_id="view" category="object" condition_expr="" url_expr="string:${object_url}" visible="True"> <permission value="View"/> </action> <action title="Edit" action_id="edit" category="object" condition_expr="" url_expr="string:${object_url}/edit" visible="True"> <permission value="Modify portal content"/> </action> </object>
example.conference/example/conference/profiles/default/types/example.conference.session.xml
<?xml version="1.0"?> <object name="example.conference.session" meta_type="Dexterity FTI" i18n:domain="example.conference" xmlns:i18n="http://xml.zope.org/namespaces/i18n"> <!-- Basic metadata --> <property name="title" i18n:translate="">Session</property> <property name="description" i18n:translate="">A session on the program</property> <property name="content_icon">document_icon.gif</property> <property name="allow_discussion">True</property> <property name="global_allow">False</property> <property name="filter_content_types">True</property> <property name="allowed_content_types" /> <!-- schema interface --> <property name="schema">example.conference.session.ISession</property> <!-- class used for content items --> <property name="klass">plone.dexterity.content.Item</property> <!-- add permission --> <property name="add_permission">cmf.AddPortalContent</property> <!-- enabled behaviors --> <property name="behaviors"> <element value="plone.app.content.interfaces.INameFromTitle" /> </property> <!-- View information --> <property name="default_view">view</property> <property name="default_view_fallback">False</property> <property name="view_methods"> <element value="view"/> </property> <!-- Method aliases --> <alias from="(Default)" to="(dynamic view)"/> <alias from="edit" to="@@edit"/> <alias from="sharing" to="@@sharing"/> <alias from="view" to="(selected layout)"/> <!-- Actions --> <action title="View" action_id="view" category="object" condition_expr="" url_expr="string:${object_url}" visible="True"> <permission value="View"/> </action> <action title="Edit" action_id="edit" category="object" condition_expr="" url_expr="string:${object_url}/edit" visible="True"> <permission value="Modify portal content"/> </action> </object>
example.conference/example/conference/profiles/default/types/example.conference.program.xml
<?xml version="1.0"?> <object name="example.conference.program" meta_type="Dexterity FTI" i18n:domain="example.conference" xmlns:i18n="http://xml.zope.org/namespaces/i18n"> <!-- Basic metadata --> <property name="title" i18n:translate="">Program</property> <property name="description" i18n:translate="">A conference program</property> <property name="content_icon">folder_icon.gif</property> <property name="allow_discussion">True</property> <property name="global_allow">True</property> <property name="filter_content_types">True</property> <property name="allowed_content_types"> <element value="example.conference.session" /> </property> <!-- schema interface --> <property name="schema">example.conference.program.IProgram</property> <!-- class used for content items --> <property name="klass">plone.dexterity.content.Container</property> <!-- add permission --> <property name="add_permission">cmf.AddPortalContent</property> <!-- enabled behaviors --> <property name="behaviors"> <element value="plone.app.content.interfaces.INameFromTitle" /> </property> <!-- View information --> <property name="default_view">view</property> <property name="default_view_fallback">False</property> <property name="view_methods"> <element value="view"/> </property> <!-- Method aliases --> <alias from="(Default)" to="(dynamic view)"/> <alias from="edit" to="@@edit"/> <alias from="sharing" to="@@sharing"/> <alias from="view" to="(selected layout)"/> <!-- Actions --> <action title="View" action_id="view" category="object" condition_expr="" url_expr="string:${object_url}" visible="True"> <permission value="View"/> </action> <action title="Edit" action_id="edit" category="object" condition_expr="" url_expr="string:${object_url}/edit" visible="True"> <permission value="Modify portal content"/> </action> </object>
bin/buildoutして利用できるアドオンにします。
とりあえず、使えるようになりました。
ちなみに、TTWでファイルから作成したContent Typeを編集できるようになっています。
次回のハッカソンでも続けていきます。
ハッカソン後の懇親会で話をしているうちに、PyQtをやるべきだという気になってきました。
あとは、Common Lisp再開です。