Reference

« Return to page index

Reference manual for Dexterity developers

1. Fields

The standard schema fields

The following tables shows the most common field types for use in Dexterity schemata. See the documentation on creating schemata for information about how to use these.

Field properties

Fields are initialised with properties passed in their constructors. To avoid having to repeat the available properties for each field, we'll list them once here, grouped into the interfaces that describe them. You'll see those interfaces again in the tables below that describe the various field types. Refer to the table below to see what properties a particular interface implies.

Interface Property Type Description
IField title unicode The title of the field. Used in the widget.
  description unicode A description for the field. Used in the widget. 
  required bool Whether or not the field is required. Used for form validation. The default is True
  readonly bool Whether or not the field is read-only. Default is False
  default The default value for the field. Used in forms and sometimes as a fallback value. Must be a valid value for the field if set. The default is None.
  missing_value A value that represents "this field is not set". Used by form validation. Defaults to None. For lists and tuples, it is sometimes useful to set this to an empty list/tuple.
IMinMaxLen min_length int The minimum required length. Used for string fields. Default is 0.
  max_length int The maximum allowed length. Used for string fields. Default is None (no check).
IMinMax min
The minimum allowed value. Must be a valid value for the field, e.g. for an Int field this should be an integer. Default is None (no check).
  max
The maximum allowed value. Must be a valid value for the field, e.g. for an Int field this should be an integer. Default is None (no check).
ICollection value_type   Another Field instance that describes the allowable values in a list, tuple or other collection. Must be set for any collection field. One common usage is to set this to a Choice, to model a multi-selection field with a vocabulary.
  unique bool Whether or not values in the collection must be unique. Usually not set directly - use a Set or Frozenset to guarantee uniqueness in an efficient way. 
IDict key_type   Another Field instance that describes the allowable keys in a dictionary. Similar to the value_type of a collection. Must be set.
  value_type   Another Field instance that describes the allowable values in a dictionary. Similar to the value_type of a collection. Must be set.
IObject schema Interface An interface that must be provided by any object stored in this field.
IRichText default_mime_type str Default MIME type for the input text of a rich text field. Defaults to text/html.
  output_mime_type str Default output MIME type for the transformed value of a rich text field. Defaults to text/x-html-safe. There must be a transformation chain in the portal_transforms tool that can transform from the input value to the output value for the output property of the RichValue object to contain a value.
allowed_mime_types tuple A list of allowed input MIME types. The default is None, in which case the site-wide settings (from the Markup control panel) will be used. 

Field types

The following tables describe the most commonly used field types, grouped by the module from which they can be imported.

Fields in zope.schema

Name Type Description Properties
Choice N/A Used to model selection from a voacabulary, which must be supplied. Often used as the value_type of a selection field. The value type is the value of the terms in the vocabulary. See vocabularies
Bytes str  Used for binary data.  IField, IMinMaxLen 
ASCII  str  ASCII text (multi-line)  IField, IMinMaxLen
BytesLine str  A single line of binary data, i.e. a Bytes with newlines disallowed  IField, IMinMaxLen
ASCIILine str A single line of ASCII text IField, IMinMaxLen
Text unicode Unicode text (multi-line). Often used with a WYSIWYG widget, although the default is a text area. IField, IMinMaxLen
TextLine unicode A single line of Unicode text IField, IMinMaxLen
Bool bool True or False IField 
Int int, long An integer number. Both ints and longs are allowed.  IField, IMinMax
Float float A floating point number. IField, IMinMax
Tuple tuple A tuple (non-mutable) IField, ICollection, IMinMaxLen
List list  A list IField, ICollection, IMinMaxLen
Set set  A set IField, ICollection, IMinMaxLen
Frozenset frozenset A frozenset (non-mutable) IField, ICollection, IMinMaxLen
Password unicode Stores a simple string, but implies a password widget.  IField, IMinMaxLen
Dict dict  Stores a dictionary. Both key_type and value_type must be set to fields. IField, IMinMaxLen, IDict
Datetime datetime Stores a Python datetime (not a Zope 2 DateTime) IField, IMinMax 
Date date  Stores a python date  IField, IMinMax 
Timedelta timedelta Stores a python timedelta  IField, IMinMax 
SourceText unicode A textfield intended to store source text (e.g. HTML or Python code)  IField, IMinMaxLen 
Object N/A Stores a Python object that conforms to the interface given as the schema. There is no standard widget for this.  IField, IObject 
URI str A URI (URL) string  IField, MinMaxLen 
Id str A unique identifier - either a URI or a dotted name.  IField, IMinMaxLen 
DottedName str A dotted name string.  IField, IMinMaxLen 
InterfaceField Interface A Zope interface.  IField
Decimal Decimal Stores a Python Decimal. Requires version 3.4 or later of zope.schema. Not available by default in Zope 2.10.  IField, IMinMax 

Fields in plone.namedfile.field

See plone.namedfile and plone.formwidget.namedfile for more details.

Name Type Description Properties
NamedFile NamedFile A binary uploaded file. Normally used with the widget from plone.formwidget.namedfile. IField
NamedImage  NamedImage A binary uploaded image. Normally used with the widget from plone.formwidget.namedfile IField 
NamedBlobFile  NamedBlobFile A binary uploaded file stored as a ZODB BLOB. Requires the [blobs] extra to plone.namedfile. Otherwise identical to NamedFile IField 
NamedBlobImage NamedBlobImage A binary uploaded image stored as a ZODB BLOB. Requires the [blobs] extra to plone.namedfile. Otherwise identical to NamedImage. IField

Fields in z3c.relationfield.schema

See z3c.relationfield for more details

Name Type Description Properties
Relation RelationValue Stores a single RelationValue. IField
RelationList list A List field that defaults to Relation as the value type See List
RelationChoice RelationValue A Choice field intended to store RelationValue's See Choice

Fields in plone.app.textfield

See plone.app.textfield for more details

Name Type Description Properties
RichText RichTextValue Stores a RichTextValue, which encapsulates a raw text value, the source MIME type, and a cached copy of the raw text transformed to the default output MIME type. IField, IRichText

2. Widgets

Standard and common third party widgets

Most of the time, you will use the standard widgets provided by z3c.form. To learn more about z3c.form widgets, see the z3c.form documentation. To learn about setting custom widgets for Dexterity content types, see the schema introduction.

The table below shows some commonly used custom widgets.

Widget Imported from Field Description
WysiwygFieldWidget plone.app.z3cform.wysiwyg Text  Use Plone's standard WYSIWYG HTML editor on a standard text field. Note that if you used a RichText field, you will get the WYSIWYG editor automatically.
RichTextWidget plone.app.textfield.widget RichText Use Plone's standard WYSIWYG HTML editor on a RichText field. This also allows text-based markup such as reStructuredText.
AutocompleteFieldWidget plone.formwidget.autocomplete Choice Autocomplete widget based on jQuery Autocomplete. Requires a Choice field with a query source. See vocabularies.
       
AutocompleteMultiFieldWidget plone.formwidget.autocomplete Collection  Multi-select version of the above. Used for a List, Tuple, Set or Frozenset with a Choice value_type. 
ContentTreeFieldWidget plone.formwidget.contenttree RelationChoice Content browser. Requires a query source with content objects as values.
MultiContentTreeFieldWidget plone.formwidget.contenttree RelationList Content browser. Requires a query source with content objects as values.
NamedFileFieldWidget plone.formwidget.namedfile NamedFile  A file upload widget 
NamedImageFieldWidget plone.formwidget.namedimage  NamedImage  An image upload widget 
TextLinesFieldWidget plone.z3cform.textlines  Collection  One-per-line list entry for List, Tuple, Set or Frozenset fields. Requires a value_type of TextLine or ASCIILine. 
SingleCheckBoxFieldWidget z3c.form.browser.checkbox Bool A single checkbox for true/false.
CheckBoxFieldWidget z3c.form.browser.checkbox  Collection  A set of checkboxes. Used for Set or Frozenset fields with a Choice value_type and a vocabulary.

3. Standard behaviors

A list of common behaviors that ship with Dexterity

Dexterity ships with several standard behaviors. The following table shows the interfaces you can list in the FTI behaviors properties and the resultant form fields and interfaces.

Interface Description
plone.app.dexterity.behaviors.metadata.IBasic Adds the standard title and description fields
plone.app.dexterity.behaviors.metadata.ICategorization Adds the Categorization fieldset and fields
plone.app.dexterity.behaviors.metadata.IPublication Adds the Dates fieldset and fields
plone.app.dexterity.behaviors.metadata.IOwnership Adds the Ownership fieldset and fields
plone.app.dexterity.behaviors.metadata.IDublinCore A single behavior that includes all the Dublin Core fields of the behaviors above
plone.app.content.interfacess.INameFromTitle Causes the content item's name to be calculated from the title attribute (which you must ensure is present and correctly set). Not a form field provider.
plone.app.dexterity.behaviors.metadata.IRelatedItems Adds the Related items field to the Categorization fieldset. 

4. Form schema hints

Directives which can be used to configure forms from schemata

Dexterity uses the plone.autoform package to configure its z3c.form-based add and edit forms. This allows a schema to be annotated with "form hints", which are used to configure the form.

The easiest way to apply form hints in Python code is to use the directives from plone.directives.form and plone.directives.dexterity. These directives are used when the package is "grokked" (via the <grok:grok package="." /> ZCML directive) to apply the form hints to the interface where they are found. For this process to work, the schema must derive from plone.directives.form.Schema. Directives can be placed anywhere in the class body. By convention they are kept next to the fields they apply to.

For example, here is a schema that omits a field:

from plone.directives import form
from zope import schema

class ISampleSchema(form.Schema):
    
    title = schema.TextLine(title=u"Title")

    form.omitted('additionalInfo')
    additionalInfo = schema.Bytes()

The form directives take parameters in the form of a list of field names, or a set of field name/value pairs as keyword arguments. Each directive can be used zero or more times.

Form directives

The form directives in the plone.directives.form package are shown below.

Name Description
widget Specify an alternate widget for a field. Pass the field name as a key and a widget as the value. The widget can either be a z3c.form widget instance or a string giving the dotted name to one.
omitted Omit one or more fields from forms. Takes a sequence of field names as parameters.
mode Set the widget mode for one or more fields. Pass the field name as a key and the string 'input', 'display' or 'hidden' as the value.
order_before Specify that a given field should be rendered before another. Pass the field name as a key and name of the other field as a value. If the other field is in a supplementary schema (i.e. one from a behaviour), its name will be e.g. "IOtherSchema.otherFieldName". Alternatively, pass the string "*" to put a field first in the form.
order_after  The inverse of order_before(), putting a field after another. Passing "*" will put the field at the end of the form.
primary Designate a given field as the primary field in the schema. This is not used for form rendering, but is used for WebDAV marshaling of the content object.
fieldset Creates a fieldset (rendered in Plone as a tab on the edit form).

The code sample below illustrates each of these directives:

from plone.directives import form
from zope import schema
from plone.app.z3cform.wysiwyg import WysiwygFieldWidget

class ISampleSchema(form.Schema):

    # A fieldset with id 'extra' and label 'Extra information' containing
    # the 'footer' and 'dummy' fields. The label can be omitted if the
    # fieldset has already been defined.
    
    form.fieldset('extra',
            label=u"Extra information",
            fields=['footer', 'dummy']
        )

    # Here a widget is specified as a dotted name.
    # The body field is also designated as the priamry field for this schema
    
    form.widget(body='plone.app.z3cform.wysiwyg.WysiwygFieldWidget')
    form.primary('body')
    body = schema.Text(
            title=u"Body text",
            required=False,
            default=u"Body text goes here"
        )

    # The widget can also be specified as an object
    
    form.widget(footer=WysiwygFieldWidget)
    footer = schema.Text(
            title=u"Footer text",
            required=False
        )
    
    # An omitted field. Use form.omitted('a', 'b', 'c') to omit several fields
        
    form.omitted('dummy')
    dummy = schema.Text(
            title=u"Dummy"
        )
    
    # A field in 'hidden' mode
    
    form.mode(secret='hidden')
    secret = schema.TextLine(
            title=u"Secret",
            default=u"Secret stuff"
        )
        
    # This field is moved before the 'description' field of the standard
    # IBasic behaviour, if this is in use.

    form.order_before(importantNote='IBasic.description')
    importantNote = schema.TextLine(
            title=u"Important note",
        )

Security directives

The security directives in the plone.directives.dexterity package are shown below. Note that these are also used to control reading and writing of fields on content instances.

Name Description
read_permission Set the (Zope 3) name of a permission required to read the field's value. Pass the field name as a key and the permission name as a string value. Among other things, this controls the field's appearance in display forms.
write_permission Set the (Zope 3) name of a permission required to write the field's value. Pass the field name as a key and the permission name as a string value. Among other things, this controls the field's appearance in add and edit forms.

The code sample below illustrates each of these directives:

from plone.directives import form, dexterity
from zope import schema

class ISampleSchema(form.Schema):

    # This field requires the 'cmf.ReviewPortalContent' to be read and
    # written
    
    dexterity.read_permission(reviewNotes='cmf.ReviewPortalContent')
    dexterity.write_permission(reviewNotes='cmf.ReviewPortalContent')
    reviewNotes = schema.Text(
            title=u"Review notes",
            required=False,
        )

5. Value and validator adaptors

Handy Decorators to set computed defaults and dynamic validators

Decorators from plone.directives.form allow you to set dynamic defaults and validators for schema fields. These are used outside the interface class, after its declaration.

Defaults

Use the plone.directives.form.default_value decorator to create an adaptor to dynamically set a default. For example, to set a Datetime field to default to the current time:

import datetime
from plone.directives import form
from zope import schema

class IMySchema(form.Schema):

    start = schema.Datetime(title=u"Start Date")

@form.default_value(field=IMySchema['start'])
def startDefaultValue(data):
    return datetime.datetime.today()

Validators

Use the plone.directives.form.validator decorator to create an adaptor to validate field input. For example, to validate that a field is not entered all uppercase:

from plone.directives import form
from zope import schema

class IMySchema(form.Schema):

    title = schema.TextLine(title=u"Title")

@form.validator(field=IMySchema['title'])
def validateTitle(value):
    if value and value == value.upper():
        raise schema.ValidationError(u"Please don't shout")

 

6. Manipulating content objects

Common APIs used to manipulate Dexterity content objects

In this section, we will describe some of the more commonly used APIs that can be used to inspect and manipulate Dexterity content objects. In most cases, the content object is referred to as context, its parent folder is referred to as folder, and the type name is example.type. Relevant imports are shown with each code snippet, though of course you are more likely to place those at the top of the relevant code module.

Content object creation and folder manipulation

This section describes means to create objects and manipulate folders.

Creating a content object

The simplest way to create a content item is via its factory:

from zope.component import createObject
context = createObject('example.type')

At this point, the object is not acquisition wrapped. You can wrap it explicitly by calling:

wrapped = context.__of__(folder)

However, it's normally better to add the item to a folder and then re-get it from the folder.

Note that the factory is normally installed as a local utility, so the createObject() call will only work once you've traversed over the Plone site root.

There is a convenience method that can be used to create a Dexterity object. It is mostly useful in tests:

from plone.dexterity.utils import createContent
context = createContent('example.type', title=u"Foo")

Any keyword arguments are used to set properties on the new instance (via setattr() on the newly created object). This method relies on being able to look up the FTI as a local utility, so again you must be inside the site for it to work.

Adding an object to a container

Once an object has been created, it can be added to a container. If the container is a Dexterity container, or another container that supports a dict API (e.g. a Large Plone Folder in Plone 3 or a container based on plone.folder), you can do:

folder['some_id'] = context

You should normally make sure that the id property of the object is the same as the id used in the container.

If the object only supports the basic OFS API (as is the case with standard Plone Folders in Plone 3), you can use the _setObject() method:

folder._setObject('some_id') = context

Note that both of these approaches bypass any type checks, i.e. you can add items to containers that would not normally allow this type of content. Dexterity comes with a convenience function, useful in tests, to simulate the checks performed when content is added through the web:

from plone.dexterity.utils import addContentToContainer
addContentToContainer(folder, context)

This will also invoke a name chooser and set the object's id accordingly, so things like the title-to-id behavior should work. As before, this relies on local components, so you must have traversed into a Plone site (PloneTestCase takes care of this for you).

To bypass folder constraints, you can use this function and pass checkConstraints=False.

You can also both create and add an object in one call:

from plone.dexterity.utils import createContentInContainer
createContentInContainer(folder, 'example.type', title=u"Foo")

Again, you can pass checkConstraints=False to bypass folder constraints, and pass object properties as keyword arguments.

Finally, you can use the invokeFactory() API, which is similar, but more generic in that it can be used for any type of content, not just Dexterity content:

new_id = folder.invokeFactory('example.type', 'some_id')
context = folder['new_id']

This always respects add constraints, including add permissions and the current user's roles.

Getting items from a folder

Dexterity containers and other containers based on plone.folder support a dict-like API to obtain and manipulate items in folders. For example, to obtain an (acquisition-wrapped) object by name:

context = folder['some_id']

Folders can also be iterated over, and you can all items(), keys(), values() and so on, treating the folder as a dict with string keys and content objects as values.

Dexterity containers also support the more basic OFS API. You can call objectIds() to get keys, objectValues() to get a list of content objects, objectItems() to get an items()-like dict,and hasObject(id) to check if an object exists in a container.

Removing items from a folder

Again, Dexterity containers act like dictionaries, and so implement __delitem__:

del folder['some_id']

The OFS API uses the _delObject() function for the same purpose:

folder._delObject('some_id')

Object introspection

This section describes means of getting information about an object.

Obtaining an object's schema interface

A content object's schema is an interface, i.e. an object of type zope.interface.interface.InterfaceClass.

from zope.app.content import queryContentType
schema = queryContentType(context)

The schema can now be inspected. For example:

from zope.schema import getFieldsInOrder
fields = getFieldsInOrder(schema)

Finding an object's behaviors

To find all behaviors supported by an object, use the plone.behavior API:

from plone.behavior.interfaces import IBehaviorAssignable
assignable = IBehaviorAssignable(context)
for behavior in assignable.enumerateBehaviors():
    behavior_schema = behavior.interface
    adapted = behavior_schema(context)
    ...

The objects returned are instances providing plone.behavior.interfaces.IBehavior. To get the behavior schema, use the interface property of this object. You can inspect this and use it to adapt the context if required.

Getting the FTI

To obtain a Dexterity FTI, look it up as a local utility:

from zope.component import getUtility
from plone.dexterity.interfaces import IDexterityFTI
fti = getUtility(IDexterityFTI, name='example.type')

The returned object provides plone.dexterity.interfaces.IDexterityFTI. To get the schema interface for the type from the FTI, you can do:

schema = fti.lookupSchema()

Getting the object's parent folder

A Dexterity item in a Dexterity container should have the __parent__ property set, pointing to its containment parent:

folder = context.__parent__

Items in standard Plone folders won't have this property set, at least not in Plone 3.x.

The more general approach relies on acquisition:

from Acquisition import aq_inner, aq_parent
folder = aq_parent(aq_inner(context))

Workflow

This section describes ways to inspect an object's workflow state and invoke transitions.

Obtaining the workflow state of an object

To obtain an object's workflow state, ask the portal_workflow tool:

from Products.CMFCore.utils import getToolByName
portal_workflow = getToolByName(context, 'portal_workflow')
review_state = portal_workflow.getInfoFor(context, 'review_state')

This assumes that the workflow state variable is called review_state, as is the case for almost all workflows.

Invoking a workflow transition

To invoke a transition:

portal_workflow.doActionFor(context, 'some_transition')

The transition must be available in the current workflow state, for the current user. Otherwise, an error will be raised.

Cataloging and indexing

This section describes ways of indexing an object in the portal_catalog tool.

Reindexing the object

Objects may need to be reindexed if they are modified in code. The best way to reindex them is actually to send an event and let Dexterity's standard event handlers take care of this:

from zope.lifecycleevent import modified
modified(context)

In tests, it is sometimes necessary to reindex explicitly. This can be done with:

context.reindexObject()

You can also pass specific index names to reindex, if you don't want to reindex everything:

context.reindexObject(idxs=['Title', 'sortable_title'])

This method comes from the Products.CMFCore.CMFCatalogAware.CMFCatalogAware mix-in class.

Security

This section describes ways to check and modify permissions. For more information, see the section on permissions.

Checking a permission

To check a permission by its Zope 3 name:

from zope.security import checkPermission
checkPermission('zope2.View', context)

Note: In a test, you may get an AttributeError when calling this method. To resolve this, call newInteraction() from Products.Five.security in your test setup (e.g. the afterSetUp() method).

To use the Zope 2 permission title:

from AccessControl import getSecurityManager
getSecurityManager().checkPermission('View', context)

Sometimes, normally in tests, you want to know which roles have a particular permission. To do this, use:

roles = [r['name'] for r in context.rolesOfPermission('View') if r['selected']]

Again, note that this uses the Zope 2 permission title.

Changing permissions

Normally, permissions should be set with workflow, but in tests it is often useful to manipulate security directly:

context.manage_permission('View', roles=['Manager', 'Owner'], acquire=True)

Again note that this uses the Zope 2 permission title.

Content object properties and methods

The following table shows the more important properties and methods available on Dexterity content objects. In addition, any field described in the type's schema will be available as a property, and can be read and set using normal attribute access.

Property/method Type Description
__name__ unicode The name (id) of the object in its container. This is a unicode string to be consistent with the Zope 3 IContained interface, although in reality it will only ever contain ASCII characters, since Zope 2 does not support non-ASCII URLs.
id str The name (id) of the object in its container. This is an ASCII string encoding of the __name__.
getId() str Returns the value of the id property.
isPrincipaFolderish bool/int True (or 1) if the object is a folder. False (or 0) otherwise.
portal_type str The portal_type of this instance. Should match an FTI in the portal_types tool. For Dexterity types, should match a local utility providing IDexterityFTI. Note that the portal_type is a per-instance property set upon creation (by the factory), and should not be set on the class.
meta_type str A Zope 2 specific way to describe a class. Rarely, if ever, used in Dexterity. Do not set it on your own classes unless you know what you're doing.
title_or_id() str Returns the value of the title property or, if this is not set, the id property.
absolute_url() str The full URL to the content object. Will take virtual hosting and the current domain into account.
getPhysicalPath() tuple A sequence of string path elements from the application root. Stays the same regardless of virtual hosting and domain. A common pattern is to use '/'.join(context.getPhysicalPath()) to get a string representing the path to the Zope application root. Note that it is not safe to construct a relative URL from the path, because it does not take virtual hosting into account.
getIcon() str Returns a string suitable for use in the src attribute of an <img /> tag to get the icon of the content object.
title unicode/str Property representing the title of the content object. Usually part of an object's schema or provided by the IBasic behavior. The default is an empty string.
Title() unicode/str Dublin Core accessor for the title property. Set the title by modifying this property. You can also use setTitle().
listCreators() tuple A list of user ids for object creators. The first creator is normally the owner of the content object. You can set this list using the setCreators() method.
Creator() str The first creator returned by the listCreators() method. Usually the owner of the content object.
Subject() tuple Dublin Core accessor for item keywords. You can set this list using the setSubject() method.
Description() unicode/str Dublin Core accessor for the description property, which is usually part of an object's schema or provided by the IBasic behavior. You can set the description by setting the description attribute, or using the setDescription() method.
listContributors() tuple Dublin Core accessor for the list of object contributors. You can set this with setContributors().
Date() str Dublin Core accessor for the default date of the content item, in ISO format. Uses the effective date is set, falling back on the modification date. 
CreationDate() str Dublin Core accessor for the creation date of the content item, in ISO format.
EffectiveDate() str Dublin Core accessor for the effective publication date of the content item, in ISO format. You can set this by passing a DateTime object to setEffectiveDate().
ExpirationDate() str Dublin Core accessor for the content expiration date, in ISO format. You can set this by passing a DateTime object to setExpirationDate().
ModificationDate() str Dublin Core accessor for the content last-modified date, in ISO format.
Language() str Dublin Core accessor for the content language. You can set this using setLanguage().
Rights() str Dublin Core accessor for content copyright information. You can set this using setRights().
created() DateTime Returns the Zope 2 DateTime for the object's creation date. If not set, returns a "floor" date of January 1st, 1970.
modified() DateTime Returns the Zope 2 DateTime for the object's modification date. If not set, returns a "floor" date of January 1st, 1970.
effective() DateTime Returns the Zope 2 DateTime for the object's effective date. If not set, returns a "floor" date of January 1st, 1970.
expires() DateTime Returns the Zope 2 DateTime for the object's expiration date. If not set, returns a "floor" date of January 1st, 1970.