building content types with dexterity
Post on 08-May-2015
4.331 Views
Preview:
DESCRIPTION
TRANSCRIPT
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
top related