35. Dexterity: Reference#
This chapter documents all types fields, widgets, directives that you can use with dexterity.
35.1. Fields included in Plone#
This is a schema with examples for all field-types that are shipped with Plone by default. They are arranged in fieldsets:
- Default
Textline, Text, Boolean, Richtext (html), Email
- Number fields
Integer, Float
- Date and time fields
Datetime, Date, Time, Timedelta
- Choice and Multiple Choice fields
Choice, Choice with radio widget, Choice with Select2 widget, Choice with named vocabulary, List, List with checkboxes, List with Select2 widget, List with values from named vocabulary but open to additions, Tuple, Set, Set with checkboxes
- Relation fields
Relationchoice, Relationlist
- File fields
File, Image
- Other fields
Uri, Sourcetext, Ascii, Bytesline, Asciiline, Pythonidentifier, Dottedname, Dict, Dict with Choice
1# -*- coding: utf-8 -*-
2from plone.app.multilingual.browser.interfaces import make_relation_root_path
3from plone.app.textfield import RichText
4from plone.app.z3cform.widget import AjaxSelectFieldWidget
5from plone.app.z3cform.widget import RelatedItemsFieldWidget
6from plone.app.z3cform.widget import SelectFieldWidget
7from plone.autoform import directives
8from plone.dexterity.content import Container
9from plone.namedfile.field import NamedBlobFile
10from plone.namedfile.field import NamedBlobImage
11from plone.schema.email import Email
12from plone.supermodel import model
13from plone.supermodel.directives import fieldset
14from plone.supermodel.directives import primary
15from ploneconf.site import _
16from z3c.form.browser.checkbox import CheckBoxFieldWidget
17from z3c.form.browser.radio import RadioFieldWidget
18from z3c.relationfield.schema import Relation
19from z3c.relationfield.schema import RelationChoice
20from z3c.relationfield.schema import RelationList
21from zope import schema
22from zope.interface import implementer
23
24
25class IExample(model.Schema):
26 """Dexterity-Schema with all field-types."""
27
28 # The most used fields
29 # textline, text, bool, richtext, email
30
31
32 fieldset(
33 'numberfields',
34 label=u'Number fields',
35 fields=('int_field', 'float_field'),
36 )
37
38 fieldset(
39 'datetimefields',
40 label=u'Date and time fields',
41 fields=('datetime_field', 'date_field', 'time_field', 'timedelta_field'),
42 )
43
44 fieldset(
45 'choicefields',
46 label=u'Choice and Multiple Choice fields',
47 fields=(
48 'choice_field',
49 'choice_field_radio',
50 'choice_field_select',
51 'choice_field_voc',
52 'list_field',
53 'list_field_checkbox',
54 'list_field_select',
55 'list_field_voc_unconstrained',
56 'tuple_field',
57 'set_field',
58 'set_field_checkbox',
59 ),
60 )
61
62 fieldset(
63 'relationfields',
64 label=u'Relation fields',
65 fields=('relationchoice_field', 'relationlist_field'),
66 )
67
68 fieldset(
69 'filefields',
70 label=u'File fields',
71 fields=('file_field', 'image_field'),
72 )
73
74 fieldset(
75 'otherfields',
76 label=u'Other fields',
77 fields=(
78 'uri_field',
79 'sourcetext_field',
80 'ascii_field',
81 'bytesline_field',
82 'asciiline_field',
83 'pythonidentifier_field',
84 'dottedname_field',
85 'dict_field',
86 'dict_field_with_choice',
87 ),
88 )
89
90 primary('title')
91 title = schema.TextLine(
92 title=u'Primary Field (Textline)',
93 required=True,
94 )
95
96 text_field = schema.Text(
97 title=u'Text Field',
98 required=False,
99 missing_value=u'',
100 )
101
102 textline_field = schema.TextLine(
103 title=u'Textline field',
104 description=u'A simple input field',
105 required=False,
106 )
107
108 bool_field = schema.Bool(
109 title=u'Boolean field',
110 required=False,
111 )
112
113 choice_field = schema.Choice(
114 title=u'Choice field',
115 values=[u'One', u'Two', u'Three'],
116 required=True,
117 )
118
119 directives.widget(choice_field_radio=RadioFieldWidget)
120 choice_field_radio = schema.Choice(
121 title=u'Choice field with radio boxes',
122 values=[u'One', u'Two', u'Three'],
123 required=True,
124 )
125
126 choice_field_voc = schema.Choice(
127 title=u'Choicefield with values from named vocabulary',
128 vocabulary='plone.app.vocabularies.PortalTypes',
129 required=False,
130 )
131
132 directives.widget(choice_field_select=SelectFieldWidget)
133 choice_field_select = schema.Choice(
134 title=u'Choicefield with select2 widget',
135 vocabulary='plone.app.vocabularies.PortalTypes',
136 required=False,
137 )
138
139 list_field = schema.List(
140 title=u'List field',
141 value_type=schema.Choice(
142 values=[u'Beginner', u'Advanced', u'Professional'],
143 ),
144 required=False,
145 missing_value=[],
146 )
147
148 directives.widget(list_field_checkbox=CheckBoxFieldWidget)
149 list_field_checkbox = schema.List(
150 title=u'List field with checkboxes',
151 value_type=schema.Choice(
152 values=[u'Beginner', u'Advanced', u'Professional'],
153 ),
154 required=False,
155 missing_value=[],
156 )
157
158 directives.widget(list_field_select=SelectFieldWidget)
159 list_field_select = schema.List(
160 title=u'List field with select widget',
161 value_type=schema.Choice(
162 values=[u'Beginner', u'Advanced', u'Professional'],
163 ),
164 required=False,
165 missing_value=[],
166 )
167
168 list_field_voc_unconstrained = schema.List(
169 title=u'List field with values from vocabulary but not constrained to them.',
170 value_type=schema.TextLine(),
171 required=False,
172 missing_value=[],
173 )
174 directives.widget(
175 'list_field_voc_unconstrained',
176 AjaxSelectFieldWidget,
177 vocabulary='plone.app.vocabularies.Users'
178 )
179
180
181 tuple_field = schema.Tuple(
182 title=u'Tuple field',
183 value_type=schema.Choice(
184 values=[u'Beginner', u'Advanced', u'Professional'],
185 ),
186 required=False,
187 missing_value=(),
188 )
189
190 set_field = schema.Set(
191 title=u'Set field',
192 value_type=schema.Choice(
193 values=[u'Beginner', u'Advanced', u'Professional'],
194 ),
195 required=False,
196 missing_value={},
197 )
198
199 directives.widget(set_field_checkbox=CheckBoxFieldWidget)
200 set_field_checkbox = schema.Set(
201 title=u'Set field with checkboxes',
202 value_type=schema.Choice(
203 values=[u'Beginner', u'Advanced', u'Professional'],
204 ),
205 required=False,
206 missing_value={},
207 )
208
209 # File fields
210 image_field = NamedBlobImage(
211 title=u'Image field',
212 description=u'A upload field for images',
213 required=False,
214 )
215
216 file_field = NamedBlobFile(
217 title=u'File field',
218 description=u'A upload field for files',
219 required=False,
220 )
221
222 # Date and Time fields
223 datetime_field = schema.Datetime(
224 title=u'Datetime field',
225 description=u'Uses a date and time picker',
226 required=False,
227 )
228
229 date_field = schema.Date(
230 title=u'Date field',
231 description=u'Uses a date picker',
232 required=False,
233 )
234
235 time_field = schema.Time(
236 title=u'Time field',
237 required=False,
238 )
239
240 timedelta_field = schema.Timedelta(
241 title=u'Timedelta field',
242 required=False,
243 )
244
245 # Relation Fields
246 relationchoice_field = RelationChoice(
247 title=u"Relationchoice field",
248 vocabulary='plone.app.vocabularies.Catalog',
249 required=False,
250 )
251 directives.widget(
252 "relationchoice_field",
253 RelatedItemsFieldWidget,
254 pattern_options={
255 "selectableTypes": ["Document"],
256 "basePath": make_relation_root_path,
257 },
258 )
259
260 relationlist_field = RelationList(
261 title=u"Relationlist Field",
262 default=[],
263 value_type=RelationChoice(vocabulary='plone.app.vocabularies.Catalog'),
264 required=False,
265 missing_value=[],
266 )
267 directives.widget(
268 "relationlist_field",
269 RelatedItemsFieldWidget,
270 vocabulary='plone.app.vocabularies.Catalog',
271 pattern_options={
272 "selectableTypes": ["Document"],
273 "basePath": make_relation_root_path,
274 },
275 )
276
277 # Number fields
278 int_field = schema.Int(
279 title=u"Integer Field (e.g. 12)",
280 description=u"Allocated (maximum) number of objects",
281 required=False,
282 )
283
284 float_field = schema.Float(
285 title=u"Float field (e.g. 12.2)",
286 required=False,
287 )
288
289 # Text fields
290 email_field = Email(
291 title=u'Email field',
292 description=u'A simple input field for a email',
293 required=False,
294 )
295
296 uri_field = schema.URI(
297 title=u'URI field',
298 description=u'A simple input field for a URLs',
299 required=False,
300 )
301
302 richtext_field = RichText(
303 title=u'RichText field',
304 description=u'This uses a richtext editor.',
305 max_length=2000,
306 required=False,
307 )
308
309 sourcetext_field = schema.SourceText(
310 title=u'SourceText field',
311 required=False,
312 )
313
314 ascii_field = schema.ASCII(
315 title=u'ASCII field',
316 required=False,
317 )
318
319 bytesline_field = schema.BytesLine(
320 title=u'BytesLine field',
321 required=False,
322 )
323
324 asciiline_field = schema.ASCIILine(
325 title=u'ASCIILine field',
326 required=False,
327 )
328
329 pythonidentifier_field = schema.PythonIdentifier(
330 title=u'PythonIdentifier field',
331 required=False,
332 )
333
334 dottedname_field = schema.DottedName(
335 title=u'DottedName field',
336 required=False,
337 )
338
339 dict_field = schema.Dict(
340 title=u'Dict field',
341 required=False,
342 key_type = schema.TextLine(
343 title=u'Key',
344 required=False,
345 ),
346 value_type = schema.TextLine(
347 title=u'Value',
348 required=False,
349 ),
350 )
351
352 dict_field_with_choice = schema.Dict(
353 title=u'Dict field with key and value as choice',
354 required=False,
355 key_type = schema.Choice(
356 title=u'Key',
357 values=[u'One', u'Two', u'Three'],
358 required=False,
359 ),
360 value_type = schema.Set(
361 title=u'Value',
362 value_type=schema.Choice(
363 values=[u'Beginner', u'Advanced', u'Professional'],
364 ),
365 required=False,
366 missing_value={},
367 ),
368 )
369
370@implementer(IExample)
371class Example(Container):
372 """Example instance class"""
35.2. How fields look like#
This is how these fields look like when editing content:
35.3. 3rd party fields#
To control the avilable values of other fields or hide/show them based on user input use the Masterselect Field.
For spam-protection use collective.z3cform.norobots.
Color-Picker collective.z3cform.colorpicker
There is no Computedfield but most use-cases can be achieved with a readonly-field and a property. See the discussion
35.4. Datagrid Field#
The Datagridfield allows you to enter multiple values at once as rows in a table. Each row is a sub form defined in a separate schema.
Here is an example:
1# -*- coding: utf-8 -*-
2from collective.z3cform.datagridfield import DataGridFieldFactory
3from collective.z3cform.datagridfield import DictRow
4from plone.app.z3cform.widget import SelectFieldWidget
5from plone.autoform import directives
6from plone.supermodel import model
7from zope import schema
8from zope.interface import Interface
9
10
11class IMyRowSchema(Interface):
12
13 choice_field = schema.Choice(
14 title=u'Choice Field',
15 vocabulary='plone.app.vocabularies.PortalTypes',
16 required=False,
17 )
18 directives.widget('objective', SelectFieldWidget)
19
20 textline_field = schema.TextLine(
21 title=u'Textline field',
22 required=False,
23 )
24
25 bool_field = schema.Bool(
26 title=u'Boolean field',
27 required=False,
28 )
29
30
31class IExampleWithDatagrid(model.Schema):
32
33 title = schema.TextLine(title=u'Title', required=True)
34
35 datagrid_field = schema.List(
36 title=u'Datagrid field',
37 value_type=DictRow(title=u'Table', schema=IMyRowSchema),
38 default=[],
39 required=False,
40 )
41 directives.widget('datagrid_field', DataGridFieldFactory)
The edit-form looks like this:
The output looks like this:
35.5. Widgets#
Todo
Document all available widgets
35.6. Directives#
Directives can be placed anywhere in the class body (annotations are made directly on the class). By convention they are kept next to the fields they apply to.
For example, here is a schema that omits a field:
from plone.autoform import directives
from plone.supermodel import model
from zope import schema
class ISampleSchema(model.Schema):
title = schema.TextLine(title=u'Title')
directives.omitted('additionalInfo')
additionalInfo = schema.Bytes()
You can also handle multiple fields with one directive:
directives.omitted('field_1', 'field_2')
With the directive "mode" you can set fields to 'input', 'display' or 'hidden'.
directives.mode(additionalInfo='hidden')
You can apply directives to certain forms only. Here we drop a field from the add-form, it will still show up in the edit-form.
from z3c.form.interfaces import IAddForm
class ITask(model.Schema):
title = schema.TextLine(title=u'Title')
directives.omitted(IAddForm, 'done')
done = schema.Bool(
title=_(u'Done'),
required=False,
)
The same works for custom forms.
With the directive widget()
you can not only change the widget used for a field. With pattern_options
you can pass additional parameters to the widget. Here, we configure the datetime widget powered by the JavaScript library pickadate by adding options that are used by it. Plone passes the options to the library.
class IMeeting(model.Schema):
meeting_date = schema.Datetime(
title=_(default=u'Date and Time'),
required=False,
)
directives.widget(
'meeting_date',
DatetimeFieldWidget,
pattern_options={
'time': {'interval': 60, 'min': [7, 0], 'max': [19, 0]}},
)
Validation and default values#
In the following example we add a validator and a default value.
from zope.interface import Invalid
import datetime
def future_date(value):
if value and not value.date() >= datetime.date.today():
raise Invalid(_(u"Meeting date can not be before today."))
return True
def meeting_date_default_value():
return datetime.datetime.today() + datetime.timedelta(7)
class IMeeting(model.Schema):
meeting_date = schema.Datetime(
title=_(default=u'Date and Time'),
required=False,
constraint=future_date,
defaultFactory=meeting_date_default_value,
)
Validators and defaults can be also be made aware of the context (i.e. to check against the values of other fields).
For context aware defaults you need to use a IContextAwareDefaultFactory
. It will be passed the container for which the add form is being displayed:
from zope.interface import provider
from zope.schema.interfaces import IContextAwareDefaultFactory
@provider(IContextAwareDefaultFactory)
def get_container_id(context):
return context.id.upper()
class IMySchema(model.Schema):
parent_id = schema.TextLine(
title=_(u'Parent ID'),
required=False,
defaultFactory=get_container_id,
)
For context-aware validators you need to use invariant()
:
from zope.interface import Invalid
from zope.interface import invariant
from zope.schema.interfaces import IContextAwareDefaultFactory
class IMyEvent(model.Schema):
start = schema.Datetime(
title=_(u'Start date'),
required=False)
end = schema.Datetime(
title=_(u"End date"),
required=False)
@invariant
def validate_start_end(data):
if data.start is not None and data.end is not None:
if data.start > data.end:
raise Invalid(_('Start must be before the end.'))
See also
To learn more about directives, validators and default values, refer to the following:
Validation (this documentation unfortunately still uses the obsolete grok technology)