Beyond through-the-web dexterity types

Comments
by Jamie Lentin on Jul 05, 2011

One of the impressive features of Dexterity is the ability to define content types through the web. However, the editor can only configure so much. We can do a lot more if we don't mind editing the configuration directly.

In a Dexterity FTI, you can specify the schema one of three ways:-

  • schema: A dotted name to an interface describing the type written in Python, as described in the developer manual.
  • model_source: An XML string representing the type. This string is generated and updated by the TTW editor. When exporting the FTI, this string will be escaped XML.
  • model_file: A path to an XML file representing the type.

Whilst developing sites we have found it useful to start off with TTW editing of types whilst prototyping what we want, then export the XML ("Export Schema Profiles" in the dexterity control panel) and add it to our sites' product. We can then empty the model_source property in the FTI and add a model_file property:-

<property name="model_file">shuttlethread.farmyard.models:animal.xml</property>

Plone.supermodel XML files

So what can you add into this XML document? In short, the plone.supermodel XML schema allows you to define a set of schemas, which approximate what you would be doing within a Python interface definition. Schemas can be named or anonymous, most of the time we will have a single anonymous schema in a file. Here is a simple example that defines three fields.

<?xml version="1.0"?>
<model xmlns="http://namespaces.plone.org/supermodel/schema">
<!-- Schema for the animal type -->
<schema>
<field name="species" type="zope.schema.TextLine">
<description />
<title>Species</title>
</field>
<field name="feeding_notes" type="plone.app.textfield.RichText">
<description />
<title>Feeding Notes</title>
</field>
<field name="passport_photo" type="plone.namedfile.field.NamedBlobImage">
<description />
<title>Passport Photo</title>
</field>
</schema>
</model>

The doctest for plone.supermodel goes into more detail about what's possible, and is a useful read.

Customisation cookbook

The following is a collection of useful snippets that can be plonked into your model files.

Choosing different widgets

Generally the default widget for a field is enough, however in some cases there is a selection. One example is a Choice field. Normally rendered with a drop-down select box, if there are only a few options then radio buttons might be more appropriate.

<model
xmlns="http://namespaces.plone.org/supermodel/schema"
xmlns:form="http://namespaces.plone.org/supermodel/form"
>
. . . .
<field name="work_permit" type="zope.schema.Choice"
form:widget="z3c.form.browser.radio.RadioFieldWidget">
<description></description>
<title>Do you require a work permit to work in the United Kingdom?</title>
<required>True</required>
<values><element>Yes</element><element>No</element></values>
</field>

Specifying a list of a field type

You may want to have a list of items, which can be created by using a zope.schema.List field like this:-

    <field name="things" type="zope.schema.List">
  <min_length>1</min_length>
<title>Things in the field</title>
<value_type type="zope.schema.Text">
<title>Thing</title>
</value_type>
</field>

The value_type can also be a zope.schema.Object, in which case the list can group multiple fields.

<field name="employment" type="zope.schema.List">
<required>False</required>
<min_length>1</min_length>
<value_type type="zope.schema.Object">
<required>False</required>
<title>Employment Detail</title>
<schema>shuttlethread.farmyard.models.IApplicationEmployment</schema>
</value_type>
</field>

Unfortunately the schema has to be a reference to a python interface, for now at least.

Using an uploaded file to name the item

If you are creating a type that is mostly a container for a file, then it may be more sensible to get the name from the file, rather than enforce users to type in a title also. Firstly you need to add the INameFromFileName behaviour within your types FTI:-

<property name="behaviors">
. . .
<element value="plone.app.dexterity.behaviors.filename.INameFromFileName"/>
</property>

Then you need to set one of your fields to be primary, which will be where the title is derived from. In your schema:-

<model xmlns="http://namespaces.plone.org/supermodel/schema"
xmlns:marshal="http://namespaces.plone.org/supermodel/marshal">
<schema>
. . .
<field name="image" type="plone.namedfile.field.NamedBlobImage"
marshal:primary="true">
<title>Background image</title>
</field>
</model>

Arranging fields into fieldsets or tabs

When editing content, available fields are arranged into tabs (or a dropdown, if there's over a certain threshold). You can use tabs to arrange your own fields by grouping them in fieldset nodes. Either use an existing name to add them to a tab, or use a new name to create a new tab.

<model xmlns="http://namespaces.plone.org/supermodel/schema"
<fieldset name="settings" label="Settings">
<field> ... </field>
</fieldset>
</model>
blog comments powered by Disqus