diff --git a/composer/schema/README.txt b/composer/schema/README.txt index 840469a..622f0bf 100644 --- a/composer/schema/README.txt +++ b/composer/schema/README.txt @@ -61,6 +61,13 @@ Field types >>> sorted(t.token for t in textFieldTypes) ['textarea', 'textline'] +Dynamic default values +---------------------- + + >>> idField = Field(u'id', default='user/title|string:???', defaultValueType='tales') + >>> idField.getDefaultValue() + '???' + Creating a schema from an interface =================================== @@ -164,6 +171,7 @@ Create a new object using a schema-based form >>> form = CreateForm(container, TestRequest(form=input)) >>> form.interface = IPerson >>> form.factory = Person + >>> form.nextUrl = 'dummy_url' # avoid hassle with IAbsoluteURL view... >>> form.getName = lambda x: x.lastName.lower() diff --git a/composer/schema/field.py b/composer/schema/field.py index 131cd2a..f47b23b 100644 --- a/composer/schema/field.py +++ b/composer/schema/field.py @@ -31,6 +31,8 @@ from zope.component import adapts from zope import component from zope.i18n.format import DateTimeParseError from zope.i18n.locales import locales +from zope.tales.engine import Engine +from zope.tales.tales import Context from cybertools.composer.base import Component from cybertools.composer.schema.interfaces import IField, IFieldInstance @@ -51,6 +53,8 @@ class Field(Component): renderFactory = None default = None default_method = None + defaultValueType = 'static' + value_type = None fieldTypeInfo = None @@ -84,11 +88,21 @@ class Field(Component): def getDefaultValue(self): if callable(self.default_method): return self.default_method() + if self.defaultValueType == 'tales': + expr = Engine.compile(self.default) + ctx = Context(Engine, self.getContextProperties()) + return expr(ctx) return self.default def setDefaultValue(self, value): self.default = value defaultValue = property(getDefaultValue, setDefaultValue) + def getDefaultValueExpr(self): + return self.default + def setDefaultValueExpr(self, value): + self.default = value + defaultValueExpr = property(getDefaultValueExpr, setDefaultValueExpr) + @property def fieldRenderer(self): return self.getFieldTypeInfo().fieldRenderer @@ -129,6 +143,9 @@ class Field(Component): fi.clientInstance = clientInstance return fi + def getContextProperties(self): + return dict(context=self, user=None) + class FieldInstance(object): @@ -152,7 +169,7 @@ class FieldInstance(object): method = getattr(self.clientInstance.context, dm, None) if method: return method() - return self.context.defaultValue + return self.context.getDefaultValue() def getRawValue(self, data, key, default=None): return data.get(key, default) diff --git a/composer/schema/interfaces.py b/composer/schema/interfaces.py index c0dfc6d..a6dbdfa 100644 --- a/composer/schema/interfaces.py +++ b/composer/schema/interfaces.py @@ -133,7 +133,7 @@ standardFieldNames = SimpleVocabulary(( )) defaultValueTypes = SimpleVocabulary(( - SimpleTerm('string', 'string', 'String'), + SimpleTerm('static', 'static', 'Static data'), SimpleTerm('tales', 'tales', 'TAL expression'), )) @@ -167,17 +167,17 @@ class IField(IComponent): required=False, default='', vocabulary=standardFieldNames,) - defaultValue = schema.TextLine( + defaultValueExpr = schema.TextLine( title=_(u'Default'), description=_(u'Value with which to pre-set the field contents. ' 'Use this also for populating a calculated field.'), required=False,) defaultValueType = schema.Choice( title=_(u'Default type'), - description=_(u'The type of the default, i.e. a fixed string ' + description=_(u'The type of the default, i.e. a static value ' u'or an expression that is used to calculate the value.'), required=False, - default='string', + default='static', vocabulary=defaultValueTypes) required = schema.Bool( title=_(u'Required'), diff --git a/composer/schema/schema.py b/composer/schema/schema.py index 3c11de2..0834481 100644 --- a/composer/schema/schema.py +++ b/composer/schema/schema.py @@ -52,6 +52,9 @@ class Schema(Template): @property def fields(self): + return self.getFields() + + def getFields(self): return self.components @property