Upload
david-glick
View
4.328
Download
1
Embed Size (px)
DESCRIPTION
David Glick's Plone Conference 2009 tutorial on building content types using Dexterity, an alternative to Archetypes.
Citation preview
Building Content Typeswith Dexterity
David GlickPlone Conference 2009
Groundwire uses the power of technology to connect people, organizations, and communities working to build a sustainable society.
What is a content type?
A way of categorizingthe items in your site
Page Something Else
Schema
Workflow
Custom view templates
Miscellaneous settings
• Placeful restrictions• Comments• Searchability• Per-type portlet assignments• etc.
History Lesson
http://commons.wikimedia.org/wiki/File:1893_Nina_Pinta_Santa_Maria_replicas.jpg
Content Management Framework (CMF)• Underlying framework for registering
types, assigning workflow• CMFDefault contains sample types which
used to be used by Plone• Not schema-based
Archetypes
• Schema-based form generation• Basis of Plone's current default content
types (ATContentTypes)• Not going away anytime soon
Dexterity
Martin Aspeli
Goals
http://www.fickr.com/photos/paul-w-locke/1662634481/sizes/m/
Make filesystem content type development sane
Make through-the-web content type development sane
Make it possible to switch back and forth between the 2
Philosophy
http://www.fickr.com/photos/ulrichsson/3519217737/
Reuse over reinvention
Produc ts .Arc he type s
Small over big
felds
widgets
base classes
storage
metadataschema
referenceengine
plone .de x te rity
plone.app.dexterity
plone.schemaeditor
z3c.form
plone.behavior
plone.app.relations
plone.directives.*
plone.autoform
plone.supermodel
Natural interaction over excessive generality
diffculty
time
Real code over generated code
Zope 3 over Zope 2
Automated testing over wishful thinking
Let's build a content type!
Installing Dexterity
[buildout]extends = http://dist.plone.org/release/3.3.1/versions.cfg http://good-py.appspot.com/release/dexterity/1.0a2
…[instance]…eggs = … plone.app.dexterity
Installing Dexterity
Dexterity Types Control Panel
Adding a Type
Adding a Type
Adding a 'Plonista' instance
Adding a 'Plonista' instance
The default 'Plonista' view
A few issues
• Bad short name for URL (“plonista”)• Showing lots of metadata fields we don't
care about• We want it to say “Name” instead of “Title”• Doesn't store anything interesting yet :)
...so let's fix it!
Behaviors
ATFile
schema
CustomATFile
s ubc la s s ing
ATFile
schema
behav iors
DexterityFile
model
thumbnailimage
name fromtitle
ratingsgeolocatable
versioned
s c hemae x te ns ion
ATFile
schema
schemaschema
schema Decolayout
Editing the 'Plonista' Behaviors
Disable this to hide the metadata
Enable this to generate short name from title
Adding a Field
Adding a Field
This will replace the title feld that used to come from the Dublin Core behavior.
Adding a Field
Editing a fieldWe are changing the title of this feld to 'Name'.
Edit a revised 'Plonista'
Rapid Prototyping
• The schema object in memory is directly modified, so changes take effect immediately.
• The changes are also serialized to XML and stored in the ZODB (in a property of the FTI), so they are persistent when Zope restarts.
Modifying a Type
• You can add, remove, and rename fields through the web.
• But, values stored in existing instances will not be automatically removed or converted. So be careful.
Some more desired refinements
• Custom add permission• Show the 'bio' field in a separate fieldset.
…we can't do these through the web (at least not yet)
Filesystem roundtripping
Web File s y s tem
Zope 3 Schema
XML schema in FTI
ContentEditing
SchemaEditing
xmlxml
XML schemaon flesystem
py
Schema asPython interface
GenericSetupimport/export
Externaltools
Exporting a type
• GenericSetup export for now;better UI coming :)
Minimal Dexterity package structure
• example.ploneconf09» /example• /ploneconf09
• /__init__.py• /configure.zcml• /profiles
• /default• /metadata.xml• /types.xml• /types
• plonista.xml
» /setup.py
setup.py
setup(name='example.ploneconf09', ... install_requires=[ 'setuptools', 'plone.app.dexterity', # -*- Extra requirements: -*- ], entry_points=""" [z3c.autoinclude.plugin] target = plone """, )
Make sure we automatically get Dexterity
Make sure we don't need a ZCML slug(in Plone 3.3 and greater)
__init__.py
# Nothing to see here; move along. :)
configure.zcml
<configure xmlns="http://namespaces.zope.org/zope" xmlns:grok="http://namespaces.zope.org/grok" xmlns:genericsetup="http://namespaces.zope.org/genericsetup" i18n_domain="example.ploneconf09">
<includeDependencies package="."/> <genericsetup:registerProfile name="default" title="Plone conference Dexterity example" directory="profiles/default" description="Installs the Dexterity example for the Plone conference." provides="Products.GenericSetup.interfaces.EXTENSION" />
</configure>
Loads ZCML for all dependency packages listed in setup.py
types.xml
metadata.xml
<?xml version="1.0"?><object name="portal_types" meta_type="Plone Types Tool"> <object name="plonista" meta_type="Dexterity FTI"/></object>
<metadata> <version>1</version> <dependencies> <dependency>profile-plone.app.dexterity:default</dependency> </dependencies></metadata>
plonista.xml<?xml version="1.0"?><object name="plonista" meta_type="Dexterity FTI" xmlns:i18n="http://xml.zope.org/namespaces/i18n"> <property name="title">Plonista</property> <property name="description">A member of the Plone community.</property> <property name="content_icon">document_icon.png</property> <property name="icon_expr">string:${portal_url}/document_icon.png</property> <property name="factory">plonista</property> <property name="link_target"></property> <property name="immediate_view">view</property> <property name="global_allow">True</property> <property name="filter_content_types">True</property> <property name="allowed_content_types"/> <property name="allow_discussion">False</property> <property name="default_view">view</property> <property name="view_methods"> <element value="view"/> </property> <property name="default_view_fallback">False</property>
plonista.xml (continued) <property name="add_permission">cmf.AddPortalContent</property> <property name="klass">plone.dexterity.content.Item</property> <property name="behaviors"> <element value="plone.app.content.interfaces.INameFromTitle"/> </property> <property name="schema"></property> <property name="model_source"><model xmlns="http://namespaces.plone.org/supermodel/schema"> <schema> <field name="title" type="zope.schema.TextLine"> <description /> <title>Name</title> </field> <field name="portrait" type="plone.namedfile.field.NamedBlobImage"> <title>Portrait</title> </field> <field name="bio" type="plone.app.textfield.RichText"> <title>Bio</title> </field> </schema> </model></property> <property name="model_file"></property>
(These are the Dexterity-specifc bits.)
Can put model in a separate fle.
Can put model in a Zope 3 schema.
plonista.xml (continued)
<alias from="(Default)" to="(selected layout)"/> <alias from="edit" to="@@edit"/> <alias from="sharing" to="@@sharing"/> <alias from="view" to="@@view"/> <action title="View" action_id="view" category="object" condition_expr="" icon_expr="" link_target="" url_expr="string:${object_url}" visible="True"> <permission value="View"/> </action> <action title="Edit" action_id="edit" category="object" condition_expr="" icon_expr="" link_target="" url_expr="string:${object_url}/edit" visible="True"> <permission value="Modify portal content"/> </action></object>
Custom add permission
• In configure.zcml:
• In plonista.xml:
• Add collective.autopermission dependency in setup.py, rerun buildout
<permission id="example.ploneconf09.AddPlonista" title="example.ploneconf09: Add plonista" />
<property name="add_permission">example.ploneconf09.AddPlonista</property>
Using a Zope 3 schema
from zope import schemafrom plone.directives import formfrom plone.namedfile.field import NamedBlobImagefrom plone.app.textfield import RichText
class IPlonista(form.Schema): title = schema.TextLine( title = u'Name', ) portrait = NamedBlobImage( title = u'Portrait', required = False, ) bio = RichText( title=u'Bio', required = False, )
• In plonista.py:
Using a Zope 3 Schema• In configure.zcml:
• Add five.grok to dependencies in setup.py• In plonista.xml:
<configure ... xmlns:grok="http://namespaces.zope.org/grok"> <grok:grok package="."/> ...</configure>
<property name="schema">example.ploneconf09.plonista.IPlonista</property> <property name="model_source"></property>
Specifying a fieldset
class IPlonista(form.Schema): … bio = RichText( title=u'Bio', required = False, ) form.fieldset( 'bio', label=u'Bio', fields=['bio'], )
More form directives
• widget – specify alternate widget• omitted – omits fields• mode – input, display, or hidden• order_before, order_after – adjust position
plone.directives.dexterity
• read_permission• write_permission
Custom view template
• In plonista.py:
from five import grokclass View(grok.View): grok.context(IPlonista) grok.require('zope2.View')
• In plonista_templates/view.pt<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" xmlns:i18n="http://xml.zope.org/namespaces/i18n" lang="en" metal:use-macro="context/main_template/macros/master" i18n:domain="example.conference"><body><metal:main fill-slot="main"> <tal:main-macro metal:define-macro="main"> <div tal:replace="structure provider:plone.abovecontenttitle" /> <h1 class="documentFirstHeading" tal:content="context/title" /> <div tal:replace="structure provider:plone.belowcontenttitle" /> <div tal:replace="structure provider:plone.abovecontentbody" /> <div tal:define="portrait nocall:context/portrait" tal:condition="nocall:portrait"><imgtal:attributes="src string:${context/absolute_url}/@@download/portrait/${portrait/filename}; height portrait/_height | nothing; width portrait/_width | nothing;" /> </div> <div tal:content="structure context/bio/output" /> <div tal:replace="structure provider:plone.belowcontentbody" /> </tal:main-macro></metal:main></body></html>
Add the package to buildout[buildout]develop = src/example.ploneconf09
[instance]… eggs = … example.ploneconf09
Install the new package
Existing content automatically provides the new schema
The custom view
The pieces
http://www.fickr.com/photos/intvgene/370973576/
five.grok
• Allows for writing configuration directives in Python and in place, instead of using ZCML.
• “Grok” a package using the following ZCML, and it will register anything its grokkers find and recognize.
<grok:grok package="." />
plone.dexterity
• Base content classes.• FTI (Factory Type Information)
provides for dynamic lookupof model and schema.
• Default edit form and view.
plone.autoform
• Dexterity renders widgets using z3c.form.• Plone.autoform makes it possible for a form
to be composed by schemas and form hints from different sources.(Main schema + behavior schemas, in the case of Dexterity.)
plone.schemaeditor
• Provides the UI for editing Zope 3 interfaces through the web.
• Dexterity integrates it with the Dexterity types control panel, but it could be used separately.
• IFieldFactory lookup determines what fields can be edited.
plone.supermodel
• Serializer translates a Zope 3 schema into XML.
• Parser translates an XML schema into a Zope 3 schema.
• Easily extensible» Field handlers found via adapter lookup» Additional metadata handlers may handle
custom XML namespaces
plone.directives.form
• Defines the form rendering hint directives that may be included in schemas for use by plone.autoform when rendering forms and views.
plone.directives.dexterity
• Grok directives for custom content classes and forms.
plone.folder
• Orderable Btree-based folder implementation.
• Will also be the basis for AT-based folders in Plone 4.
plone.behavior
• A behavior is a conditional adapter.• In Dexterity, the condition is whether the
behavior is listed in the FTI for an item.• ZCML directive for registering new
behaviors.
plone.rfc822
• Supports the marshalling of Dexterity content into RFC 822 format.
• Used to support access via WebDAV.
plone.app.dexterity
• Pulls in everything you need.• Standard behaviors.» Dublin Core» Related Items
• Dexterity types control panel.
Status report / roadmap
http://www.fickr.com/photos/brianatwebbmoto/2392041992/sizes/m/
Core functionality
Schema serialization
Automatic formgeneration
Portlet assignments
Content rules
Relations
• Not working between Archetypes and Dexterity content in the same site
Widgets
• Not as rich as Archetypes yet, but better than formlib. We have autocomplete, browse-for-content, file/image upload.
TTW schema editing
• Works fine, but needs more real-life use.
Image & file support
(via plone.namedfile & plone.formwidget.namedfile)
• No support for image scaling yet.
Text transform support
(via plone.app.textfield)
Select field support
• No way to define vocabularies through the web yet.
WebDAV support
Versioning & staging
• In progress
TTW behavior creation
Automatic migrationfrom Archetypescontent
Multi-lingual content
• Some discussion, but no code yet.
Link integrity checks
Upcoming releases
• Second alpha release was on Oct. 12• First beta release coming soon
Compatibility
• Plone 3• Plone 4 compatibility coming soon
Performance
Further information
• Dexterity manual:http://plone.org/products/dexterity/documentation/manual/developer-manual
• Behaviors manual:http://plone.org/products/dexterity/documentation/manual/behaviors
• Over 30,000 words!
Example Code
• example.dexterity• example.conference
(both in the collective)
• Example code from this talk:http://svn.plone.org/svn/plone/plone.dexterity/example.ploneconf09
Thanks to everyone who has contributed to making Dexterity a reality!
http://www.fickr.com/photos/torley/2862255105/
Getting involved
• Google Code project:http://code.google.com/p/dexterity/
• Google Group:http://groups.google.com/group/dexterity-development