Oft vereinfacht es die Bedienung deutlich, wenn in Feldern Standardwerte eingetragen werden. Diese Werte werden im Hinzufügen-Formular gesetzt.
In unserem Beispiel sollen die Standardwerte für den Beginn und das Ende einer Veranstaltung eine Woche in der Zukunft liegen. Hierzu fügen wir in registration.py
folgendes hinzu:
import datetime
...
@form.default_value(field=IRegistration['start'])
def startDefaultValue(data):
# To get hold of the folder, do: context = data.context
return datetime.datetime.today() + datetime.timedelta(7)
@form.default_value(field=IRegistration['end'])
def endDefaultValue(data):
# To get hold of the folder, do: context = data.context
return datetime.datetime.today() + datetime.timedelta(10)
Der Decorator kann ein oder mehrere Unterscheidungskriterien haben. Folgende Unterscheidungskriterien sind möglich:
context
Der Kontexttyp, z.B. ein Interface
request
Der Request-Tp, z.B. ein Layer Marker Interface
view
Der Formulartyp, z.B. eine Formularinstanz oder ein Interface.
field
Die Feld-Instanz oder das Interface eines Feldes
Neben dem default_value
-Decorator gibt es noch zwei weitere Decorators:
widget
Der Widget-Typ, z.B. ein Interface
widget_label
bietet ein dynamische Label für Widgets wobei es dieselben Unterscheidungskriterien zulässt wie default_value
.
button_label
bietet dynamische Label für Tasten mit den Unterscheidungskriterien content, ``request
, form
, manager
und button
.
In der Dokumentation zu plone.directives.form finden Sie weitere Informationen hierzu.
Vokabularien werden üblicherweise zusammen mit Auswahlfeldern verwendet. Um nur eine Auswahl zuzulassen, kann das Choise
-Feld direkt verwendet werden:
class IMySchema(form.Schema):
myChoice = schema.Choice(...)
Für Multiple-Choice-Felder können List
, Tuple
, Set
oder Frozenset
mit value_type=schema.Choice
verwendet werden, also z.B.:
class IMySchema(form.Schema):
myList = schema.List(
title=u"My list",
value_type=schema.Choice(values=['red', 'green', 'blue', 'yellow']))
Ein Choice
-Feld kann eines der folgenden Argumente erhalten:
Werte aus einer Liste statischer Werte
Werte aus einer Quelle, die mit IContextSourceBinder
oder einer ISource
-Intanz angegeben werden
Werte können aus einem Vokabular stammen, das als ÌVocabulary
-Instanz oder als Name eines IVocabularyFactory
-Utility angegeben wird
term
Eintrag in ein Vokabular
token
ASCII-Zeichenkette, die beim Abschicken eines Formulars übermittelt wird um den Term eindeutig zu identifizieren.
value
Der aktuelle Wert, der in einem Objekt gespeichert wird
title
Übersetzbare Unicode-Zeichenkette
In Plone werden Ihnen bereits eine ganze Reihe von Vokabularien in plone.app.vocabularies
zur Verfügung gestellt. Die gebräuchlichsten sind:
plone.app.vocabularies.AvailableContentLanguages
Eine Liste aller verfügbaren Sprachen
plone.app.vocabularies.SupportedContentLanguages
Eine Liste aller aktuell unterstützten Sprachen
plone.app.vocabularies.Roles
Die in der Site verfügbaren Rollen
plone.app.vocabularies.PortalTypes
Eine Liste der im Portal Types Tool registrierten Artikeltypen
plone.app.vocabularies.ReallyUserFriendlyTypes
Eine Liste derjenigen Artikeltypen, die für Nutzer von Bedeutung sind
plone.app.vocabularies.Workflows
Eine Liste aller Arbeitsabläufe
plone.app.vocabularies.WorkflowStates
Eine Liste aller Arbeitsablaufstadien
plone.app.vocabularies.WorkflowTransitions
Eine Liste aller Übergänge zwischen Arbeitsablaufstadien
Mit plone.principalsource
steht uns ein weiteres Paket mit verschiedenen Vokabularien bereit, das zur Auswahl von Nutzern und Gruppen hilfreich ist:
plone.principalsource.Users
Eine Liste aller Nutzer
plone.principalsource.Groups
Eine Liste aller Gruppen
plone.principalsource.Principals
Eine Liste aller Berechtigungen für Nutzer und Gruppen
Hier ein Beispiel für ein statisches Vokabular:
from zope.schema.vocabulary import SimpleVocabulary, SimpleTerm
organisers = SimpleVocabulary(
[SimpleTerm(value=u'vsc', title=_(u'Veit Schiele Communications')),
SimpleTerm(value=u'zopyx', title=_(u'Zopyx Limited'))]
)
organiser = schema.Choice(
title=_(u"Organiser"),
vocabulary=organisers,
required=False,
)
Statische Vokabularien sind in zweierlei Hinsicht beschränkt: zum einen sind sie hartkodiert in Python, zum anderen werden die gespeicherten Werte nicht getrennt von den Labels gespeichert.
Ein dynamische Vokabular kann nun erzeugt werden indem ein sog. Context Source Binder verwendet wird. Ein solcher kann einfach aufgerufen werden durch eine Funktion oder ein Objekt mit einer __call__
-Methode, die das IContextSourceBinder
-Interface zusammen mit einem Kontext-Argument bereitstellt. Der Aufruf soll ein Vokabular ausgeben, das am einfachsten zu bekommen ist, wenn die SimpleVocabulary
-Klasse aus zope.schema
verwendet wird.
Im folgenden nun ein Beispiel für eine Funktion, die alle Nutzer einer bestimmten Gruppe zurückgibt:
from zope.schema.interfaces import IContextSourceBinder
from zope.schema.vocabulary import SimpleVocabulary
from Products.CMFCore.utils import getToolByName
@grok.provider(IContextSourceBinder)
def possibleOrganisers(context):
acl_users = getToolByName(context, 'acl_users')
group = acl_users.getGroupById('organisers')
terms = []
if group is not None:
for member_id in group.getMemberIds():
user = acl_users.getUserById(member_id)
if user is not None:
member_name = user.getProperty('fullname') or member_id
terms.append(SimpleVocabulary.createTerm(member_id, str(member_id), member_name))
return SimpleVocabulary(terms)
Das obige Beispiel kann erweitert werden indem der Gruppenname aus der Funktion herausgenommen wird und sich dann für jedes Feld unabhängig setzen lässt. Hierfür wird dann IContextSourceBinder
in eine eigene Klasse ausgelagert, die mit dem Gruppennamen initialisiert wird:
class GroupMembers(object):
"""Context source binder to provide a vocabulary of users in a given
group.
"""
grok.implements(IContextSourceBinder)
def __init__(self, group_name):
self.group_name = group_name
def __call__(self, context):
acl_users = getToolByName(context, 'acl_users')
group = acl_users.getGroupById(self.group_name)
terms = []
if group is not None:
for member_id in group.getMemberIds():
user = acl_users.getUserById(member_id)
if user is not None:
member_name = user.getProperty('fullname') or member_id
terms.append(SimpleVocabulary.createTerm(member_id, str(member_id), member_name))
return SimpleVocabulary(terms)
Sollen Vokabularien nicht nur im Kontext verfügbar sein sondern als Komponenten, werden sog. Named Vocabularies erstellt. Diese werden als named utilities registriert werden und sind anschließend in einem Schema mit ihrem Namen referenziert werden. Damit lassen sich Vokabularien in eigenständigen Paketen erstellen.
collective.vdexvocabulary erlaubt die Verwendung von IMS VDEX-Vokabularien und bietet darüberhinaus noch weitere Vorteile wie:
i18n
-Unterstützung, wie sie im IMS VDEX-Standard definiert ist.
Unterstützung für Sortierung auch von Unicode-Zeichen. sofern zope.ucol installiert ist
Einfache Registrierung mit zcml
Relationen wie sie im IMS VDEX-Standard spezifiziert sind
collective.elephantvocabulary
¶collective.elephantvocabulary ist ein Wrapper für zope.schema
-Vokabularien wodurch diese keinen ihre Einträge mehr vergessen.
plone.formwidget.autocomplete
erweitert z3c.formwidget.query
um ein nutzerfreundlicheres Interface für Felder bereitzustellen, bei dem nach der Eingabe von wenigen Zeichen bereits die möglichen Werte angezeigt werden.
Das Widget wird bereits mit plone.app.dexterity
mitgeliefert, sodass wir es einfach z.B. in registration.py
verwenden können, mit:
form.widget(organiser=AutocompleteFieldWidget)
organiser = schema.Choice(
title=_(u"Organiser"),
vocabulary=u"plone.principalsource.Users",
required=False,
)