This talk covers the basics of building content types with Dexterity, and how it compares to doing so with Archetypes; what sorts of tasks Dexterity is best suited for, and which ones it isn't ready for yet
* an update on the most recent improvements to Dexterity
9. History Lesson
http://commons.wikimedia.org/wiki/File:1893_Nina_Pinta_Santa_Maria_replicas.jpg
10. 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
11. Archetypes
• Schema-based form generation
• Basis of Plone's current default content
types (ATContentTypes)
• Not going away anytime soon
19. Small over big
Pro duc ts .Arc he ty pe s
plone.app.dexterity
base classes
metadata plone.behavior
felds schema plone.directives.*
plone.autoform
widgets
plo ne .de x te rity
storage
plone.supermodel z3c.form
reference
engine
plone.schemaeditor
plone.app.relations
29. Base class
Archetypes Dexterity
• BaseObject, usually via • plone.dexterity.content.Item or
plone.dexterity.content.Container
ATContentTypes
• fewer mixins
• many mixins
• custom subclasses
• typically need a custom typically unneeded
subclass
30. Schemas
Archetypes Dexterity
• unique schema format • Zope 3 schemas
• define a schema, assign it • Can also be represented in
to the content class's a unique XML schema
'schema' attribute format
• Associated with a content
type via the FTI in
portal_types
31. Filesystem roundtripping
We b File s y s te m
Zope 3 Schema Schema as
Python interface
Content
Editing py
Schema
Editing
xml xml External
GenericSetup tools
import/export
XML schema in XML schema
FTI on flesystem
32. Schemas
Archetypes Dexterity
From content/photo.py: From content/photo.py:
PhotoSchema = atapi.Schema(( class IPhoto(form.Schema):
# (fields here) # (fields here)
))
From profles/default/types/photo.xml:
schemata.finalizeATCTSchema(PhotoSchema,
moveDiscussion=False) <property name="schema">
example.dexgallery.dexterity.content.photo.
class Photo(base.ATCTContent): IPhoto
implements(IPhoto) </property>
meta_type = "Photo"
schema = PhotoSchema
33. Accessing fields
Archetypes Dexterity
• obj.getField('fieldname') • obj.fieldname
.get(obj) (values are simply stored
• obj.getFieldname() as attributes)
(magically generated • Use property descriptors if
accessor on the content you need custom accessor/
class) mutator logic
• __getattr__ makes sure to
get default value from
schema if there's no
attribute stored yet
34. Field security
• Controlled access (from RestrictedPython)
• Implemented using
__allow_access_to_unprotected_subobjects__
Archetypes Dexterity
• Read/write permissions • Read/write permissions
can be specified per field can be specified per field
in the schema in the schema
37. Image scaling
• Now supports arbitrary sizes, e.g.
<img tal:defne="scale photo_obj/@ @ images"
tal:replace="structure python:scale.scale('image', width=1200,
height=300, direction='keep').tag()"/>
• (supported for both Archetypes and
Dexterity in Plone 4)
38. Tags field (relations)
Archetypes Dexterity
From content/photo.py: From content/photo.py:
atapi.ReferenceField( from z3c.relationfield.schema import
'tags', RelationList, RelationChoice
storage=atapi.AnnotationStorage(), tags = RelationList(
widget=atapi.ReferenceWidget( title = _(u'Tags'),
label=_(u"Tags"), default = [],
), value_type=RelationChoice(
required=False, title = _(u'Tag'),
relationship='photo_tag', source = ObjPathSourceBinder(
allowed_types=('Document',), navigation_tree_query = {'path':
multiValued=True, {'query':'/'}},
), portal_type = 'Document',
),
),
required = False,
)
40. Indexing fields
• similar for both
• for Dexterity you may need to implement
your own SearchableText indexer, e.g.
from plone.indexer import indexer
@indexer(IPhoto)
def SearchableText(obj):
return ' '.join([obj.Title(), obj.Description(), obj.caption.output])
41. Custom views
Archetypes Dexterity
• default: base_view.cpt • default: view class in
• add a skin layer template plone.dexterity.browser.view
or browser view, register • add a skin layer template or
in the FTI browser view, register in the
FTI
42. Grok-style configuration
• Configuration via directives inline with
code, instead of via ZCML declarations. e.g.
from five import grok
class View(grok.View):
grok.context(IPhoto)
grok.require('zope2.View')
• Supported but not required
43. Custom forms
Archetypes Dexterity
• difficult • full power of z3c.form
(write custom forms that
reference fields from the
type's schema)
• or, use grok directives on the
schema to influence how
fields appear in all forms (e.g.,
custom widget, etc.)
44. Adding items
Archetypes Dexterity
• Autogenerated factory • z3c.form add form
method • Default works in many
• In Plone, portal_factory cases, but can be replaced
prevents premature by setting add_view_expr
creation and indexing in the FTI
• No content is constructed
until the form is submitted
45. Extending content types
Archetypes Dexterity
• archetypes.schemaextender • “behaviors”
• “schema extender” adapters • can provide additional
can provide additional fields fields
• “schema modifier” adapters • can mark the content item
can make arbitrary changes with a particular interface
to a schema • can be turned on/off
through the web for each
content type
46. Behaviors
s ubc la s s ing s c he m a be ha v io rs
schema e x te ns io n
ATFile schema
model
schema
schema
schema Deco thumbnail
schema
layout image
ATFile
Dexterity
versioned File name from
CustomATFile ATFile title
geolocatable
ratings
48. Geolocation behavior
• Adds a geolocation field
• Provides an adapter to store the value of
that field in an annotation
• Marks the item with IGeolocatableMarker
• Some adapters so that Products.Maps
knows how to get a geolocation from an
item with IGeolocatableMarker
49. Registering a type
Archetypes Dexterity
• registerType() after class • Just GenericSetup
definition magically (profiles/default/types/
generates Zope 2-style [Type_Id].xml)
factory methods
• boilerplate in __init__.py
finds types and completes
registration
• type configuration in
GenericSetup profile
references the factory
method
50. """Main product initializer from zope.i18nmessageid import MessageFactory
"""
_ = MessageFactory('example.dexgallery')
from zope.i18nmessageid import MessageFactory
from example.dexgallery.archetypes import config
from Products.Archetypes import atapi
from Products.CMFCore import utils
# Define a message factory for when this product is internationalised.
# This will be imported with the special name "_" in most modules. Strings
# like _(u"message") will then be extracted by i18n tools for translation.
archetypesMessageFactory = MessageFactory('example.dexgallery.archetypes')
def initialize(context):
"""Initializer called when used as a Zope 2 product.
This is referenced from configure.zcml. Regstrations as a "Zope 2 product"
is necessary for GenericSetup profiles to work, for example.
Here, we call the Archetypes machinery to register our content types
with Zope and the CMF.
"""
# Retrieve the content types that have been registered with Archetypes
# This happens when the content type is imported and the registerType()
# call in the content type's module is invoked. Actually, this happens
# during ZCML processing, but we do it here again to be explicit. Of
# course, even if we import the module several times, it is only run
# once.
content_types, constructors, ftis = atapi.process_types(
atapi.listTypes(config.PROJECTNAME),
config.PROJECTNAME)
# Now initialize all these content types. The initialization process takes
# care of registering low-level Zope 2 factories, including the relevant
# add-permission. These are listed in config.py. We use different
# permissions for each content type to allow maximum flexibility of who
# can add which content types, where. The roles are set up in rolemap.xml
# in the GenericSetup profile.
for atype, constructor in zip(content_types, constructors):
utils.ContentInit('%s: %s' % (config.PROJECTNAME, atype.portal_type),
content_types=(atype, ),
permission=config.ADD_PERMISSIONS[atype.portal_type],
extra_constructors=(constructor,),
).initialize(context)
51. Status report / roadmap
http://www.fickr.com/photos/brianatwebbmoto/2392041992/sizes/m/