Dexterity开发之一:Schema定义
Dexterity开发之一:Schema定义
http://www.315ok.org/blogfolder/292
http://www.315ok.org/logo.png
Dexterity开发之一:Schema定义
Dexterity开发之一:Schema定义
The schema is usually the first part of a content type that we write. A schema is an interface that defines fields, most of which are found in the package zope.schema.
Most Dexterity schemata derive from the class plone.directives.form.Schema,which allows certain convention-over-configuration directives to be applied, to supply hints to the standard add and edit forms, for example to hide certain fields or override the default widget used for a particular field.
For example, take the schema in cinema.py.We begin with some imports:
Next, we define a constraint function, which will be called to validate the value of the cinema code. It should return True if all is well, and raise an Invalid exception with an appropriate error message otherwise:
Form hints in the schema
By default, the generated add and edit forms will show, in order, each field from the schema and the schemata provided by any enabled behaviors, using the default widget for each field. We can supply hints to the forms (which use base classes provided by the plone.autoform package) to exert some more control over how the forms are rendered, without having to override them wholesale.
For example, consider this schema, adapted from the Dexterity Developer's Manual:
Most Dexterity schemata derive from the class plone.directives.form.Schema,which allows certain convention-over-configuration directives to be applied, to supply hints to the standard add and edit forms, for example to hide certain fields or override the default widget used for a particular field.
For example, take the schema in cinema.py.We begin with some imports:
from five import grok
from zope import schema
from plone.directives import form
from zope.interface import Invalid
from plone.app.textfield import RichText
from z3c.relationfield.schema import RelationList, RelationChoice
from plone.formwidget.contenttree import ObjPathSourceBinder
from optilux.cinemacontent import CinemaMessageFactory as _
from optilux.cinemacontent.film import IFilm
...
The standard field types are found in zope.schema, but we will also use fields from plone.app.textfield (rich text with a WYSIWYG editor) and z3c.relationfield (content references).Next, we define a constraint function, which will be called to validate the value of the cinema code. It should return True if all is well, and raise an Invalid exception with an appropriate error message otherwise:
def cinemaCodeIsValid(value):
"""Contraint function to make sure the given cinema code is valid
"""
if value:
if len(value) < 4 or len(value) > 6 or \
not value.startswith('C'):
raise Invalid(
_(u"The cinema code is not of the correct format")
)
return True
We then define the schema itself. plone.directives.form.Schema is simply a subclass of zope.interface.Interface, which acts as a marker to various grokkers that can operate on any directives in the schema.class ICinema(form.Schema):
"""A cinema
"""
We list the fields of the content type in the body of the schema. Note that standard fields such as the content's title, description, creation date, and so on are supplied by a behavior (IDublinCore), which is listed in the GenericSetup file that creates the FTI. We will show this later in this chapter.cinemaCode = schema.ASCIILine(
title=_(u"Cinema code"),
description=_(u"Code used in the bookings database"),
constraint=cinemaCodeIsValid,
)
phone = schema.TextLine(
title=_(u"Phone number"),
description=_(u"Please enter as the customer should dial"),
)
text = RichText(
title=_(u"Details"),
description=_(u"Description of the cinema"),
)
highlightedFilms = RelationList(
title=_(u"Highlighted films"),
description=_(u"Films to highlight for this cinema"),
value_type=RelationChoice(
source=ObjPathSourceBinder(
object_provides=IFilm.__identifier__
),
),
required=False,
)
For a full list of fields and their associated properties, see the reference at http://plone.org/products/dexter ... l/reference/fields.Form hints in the schema
By default, the generated add and edit forms will show, in order, each field from the schema and the schemata provided by any enabled behaviors, using the default widget for each field. We can supply hints to the forms (which use base classes provided by the plone.autoform package) to exert some more control over how the forms are rendered, without having to override them wholesale.
For example, consider this schema, adapted from the Dexterity Developer's Manual:
from five import grok
from zope import schema
from plone.directives import form, dexterity
from z3c.relationfield.schema import RelationChoice
from plone.formwidget.contenttree import ObjPathSourceBinder
from plone.formwidget.autocomplete import AutocompleteFieldWidget
from example.conference import _
from example.conference.presenter import IPresenter
class ISession(form.Schema):
...
form.widget(presenter=AutocompleteFieldWidget)
presenter = RelationChoice(
title=_(u"Presenter"),
source=ObjPathSourceBinder(
object_provides=IPresenter.__identifier__
),
required=False,
)
Here, we have specified an alternative widget for the RelationChoice field. The AutocompleteFieldWidget from plone.formwidget.autocomplete provides a 'search-as-you-type' auto-completion widget using the specified source (more on sources shortly). The Dexterity Developer's Manual contains an overview of the commonly used widgets.It is conventional to place a form directive immediately above the field it pertains to. However, the link between the field and the directive is made in arguments passed to the directive, not the placement of the directive relative to a field. In fact, most directives can optionally be passed several fields to configure at once.Other directives can be used to omit fields from the forms entirely, make hidden fields, create tabbed field sets, or order fields relative to one another. These constructs are most useful when writing behaviors or other reusable schemata,but can sometimes be useful if fine-grained control over the rendering of forms is required. See the Dexterity Developer's Manual and the documentation for details.
For forms that deviate significantly from the default, it is usually easiest to register custom add and edit forms. The Dexterity Developer's Manual contains examples of both.