added field processing and validation

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1957 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2007-08-26 10:39:43 +00:00
parent 89a3581e5b
commit 6a57f72e6c
6 changed files with 150 additions and 12 deletions

View file

@ -32,6 +32,8 @@ from cybertools.composer.schema.interfaces import IClientFactory
class SchemaView(BaseView): class SchemaView(BaseView):
formState = None
@Lazy @Lazy
def fields(self): def fields(self):
return self.context.fields return self.context.fields
@ -41,8 +43,8 @@ class SchemaView(BaseView):
return self.getData() return self.getData()
def getData(self): def getData(self):
form = self.request.form
if not self.clientName: if not self.clientName:
form = self.request.form
self.clientName = form.get('id') self.clientName = form.get('id')
clientName = self.clientName clientName = self.clientName
if not clientName: if not clientName:
@ -54,6 +56,7 @@ class SchemaView(BaseView):
instance = IInstance(client) instance = IInstance(client)
instance.template = self.context instance.template = self.context
return instance.applyTemplate() return instance.applyTemplate()
# TODO: overwrite data with values from form
def update(self): def update(self):
form = self.request.form form = self.request.form
@ -68,12 +71,17 @@ class SchemaView(BaseView):
if client is None: if client is None:
return True return True
else: else:
# if not self.hasData(form) and 'submit' not in form:
# self.request.response.redirect(self.nextUrl())
# return False
client = IClientFactory(manager)() client = IClientFactory(manager)()
clientName = self.clientName = manager.addClient(client) clientName = self.clientName = manager.addClient(client)
instance = component.getAdapter(client, IInstance, name='editor') instance = component.getAdapter(client, IInstance, name='editor')
instance.template = self.context instance.template = self.context
instance.applyTemplate(form) self.formState = formState = instance.applyTemplate(form)
#return True if formState.severity > 0:
# show form again
return True
self.request.response.redirect(self.nextUrl()) self.request.response.redirect(self.nextUrl())
return False return False

View file

@ -17,7 +17,7 @@
# #
""" """
Schema fields Schema fields and related classes.
$Id$ $Id$
""" """
@ -26,24 +26,62 @@ from zope.interface import implements
from zope import schema from zope import schema
from cybertools.composer.base import Component from cybertools.composer.base import Component
from cybertools.composer.schema.interfaces import IField from cybertools.composer.schema.interfaces import IField, IFieldState
from cybertools.util.format import toStr, toUnicode
class Field(Component): class Field(Component):
implements(IField) implements(IField)
required = False
def __init__(self, name, title=None, renderFactory=None, **kw): def __init__(self, name, title=None, renderFactory=None, **kw):
assert name assert name
self.__name__ = name self.__name__ = name
title = title or u'' title = title or u''
self.renderFactory = renderFactory # use for rendering field content self.renderFactory = renderFactory # use for rendering field content
super(Field, self).__init__(title, __name__=name, **kw) super(Field, self).__init__(title, __name__=name, **kw)
self.title = title
for k, v in kw.items():
setattr(self, k, v)
@property @property
def name(self): def name(self):
return self.__name__ return self.__name__
@property #@property
def title(self): #def title(self):
# return self.title or self.name
def getTitleValue(self):
return self.title or self.name return self.title or self.name
def marshallValue(self, value):
return toStr(value)
def displayValue(self, value):
return toStr(value)
def unmarshallValue(self, strValue):
return toUnicode(strValue) or u''
def validateValue(self, value):
errors = []
severity = 0
if not value and self.required:
errors.append('required_missing')
severity = 5
return FieldState(self.name, errors, severity)
class FieldState(object):
implements(IFieldState)
def __init__(self, name, errors=[], severity=0, change=None):
self.name = self.__name__ = name
self.errors = errors
self.severity = severity
self.change = change

View file

@ -29,6 +29,7 @@ from zope.interface import implements
from cybertools.composer.instance import Instance from cybertools.composer.instance import Instance
from cybertools.composer.interfaces import IInstance from cybertools.composer.interfaces import IInstance
from cybertools.composer.schema.interfaces import IClient from cybertools.composer.schema.interfaces import IClient
from cybertools.composer.schema.schema import FormState
class Editor(Instance): class Editor(Instance):
@ -84,7 +85,9 @@ class ClientInstanceEditor(ClientInstance):
def applyTemplate(self, data={}, **kw): def applyTemplate(self, data={}, **kw):
""" Store the attributes described by self.template (a schema) """ Store the attributes described by self.template (a schema)
using corresponding values from the data argument. using corresponding values from the data argument.
Return the resulting form state (an object providing IFormState).
""" """
formState = FormState()
attrs = getattr(self.context, self.attrsName, None) attrs = getattr(self.context, self.attrsName, None)
if attrs is None: if attrs is None:
attrs = OOBTree() attrs = OOBTree()
@ -92,8 +95,17 @@ class ClientInstanceEditor(ClientInstance):
template = self.template template = self.template
values = attrs.setdefault(self.aspect, OOBTree()) values = attrs.setdefault(self.aspect, OOBTree())
if template is not None: if template is not None:
for c in template.components: for f in template.fields:
name = c.name name = f.name
value = f.unmarshallValue(data.get(name))
fieldState = f.validateValue(value)
if name in data: if name in data:
values[name] = data[name] oldValue = values.get(name)
if value != oldValue:
values[name] = value
fieldState.change = (oldValue, value)
formState.changed = True
formState.fieldStates.append(fieldState)
formState.severity = max(formState.severity, fieldState.severity)
return formState

View file

@ -78,7 +78,7 @@ class IField(IComponent):
description=_(u'The type of the field'), description=_(u'The type of the field'),
required=True, required=True,
default='textline', default='textline',
values=('textline', 'textarea', 'date')) values=('textline', 'textarea', 'date', 'checkbox'))
defaultValue = schema.TextLine( defaultValue = schema.TextLine(
title=_(u'Default'), title=_(u'Default'),
description=_(u'Value with which to pre-set the field contents'), description=_(u'Value with which to pre-set the field contents'),
@ -87,6 +87,61 @@ class IField(IComponent):
title=_(u'Required'), title=_(u'Required'),
description=_(u'Must a value been entered into this field?'), description=_(u'Must a value been entered into this field?'),
required=False,) required=False,)
width = schema.Int(
title=_(u'Width'),
description=_(u'The horizontal size of the field in pixels'),
default=300,
required=False,)
height = schema.Int(
title=_(u'Height'),
description=_(u'The vertical size of the field in lines '
'(only for type textarea)'),
default=3,
required=False,)
# validator = schema.Text(),
# marshaller = schema.Text(),
def marshallValue(value):
""" Return a string (possibly unicode) representation of the
value given that may be used for editing.
"""
def displayValue(value):
""" Return a string (possibly unicode) representation of the
value given that may be used for presentation.
"""
def unmarshallValue(strValue):
""" Return the internal (real) value corresponding to the string
value given.
"""
def validateValue(value):
""" Check if the value given is valid. Return an object implementing
IFieldState.
"""
class IFieldState(Interface):
""" Represents the state of a field used for editing.
"""
name = Attribute('Field name.')
change = Attribute('A tuple ``(oldValue, newValue)`` or None.')
errors = Attribute('A sequence of error infos.')
severity = Attribute("An integer giving a state or error "
"code, 0 meaning 'OK'.")
class IFormState(Interface):
""" Represents the state of all fields when editing.
"""
fieldStates = Attribute('A mapping ``{fieldName: fieldState, ...}``.')
changed = Attribute('True if one of the fields has been changed or False.')
severity = Attribute("An integer giving an overall state or error "
"code, typically the maximum of the field states' "
"severities.")
# clients # clients

View file

@ -26,7 +26,8 @@ from zope.interface import implements
from cybertools.composer.base import Component, Element, Compound from cybertools.composer.base import Component, Element, Compound
from cybertools.composer.base import Template from cybertools.composer.base import Template
from cybertools.composer.schema.interfaces import ISchema from cybertools.composer.schema.interfaces import ISchema, IFormState
from cybertools.util.jeep import Jeep
class Schema(Template): class Schema(Template):
@ -57,3 +58,14 @@ class Schema(Template):
def getManager(self): def getManager(self):
return self.manager return self.manager
class FormState(object):
implements(IFormState)
def __init__(self, fieldStates=[], changed=False, severity=0):
self.fieldStates = Jeep(fieldStates)
self.changed = changed
self.severity = severity

View file

@ -48,3 +48,16 @@ def formatNumber(num, type='decimal', lang='de'):
fmt = de.numbers.getFormatter(type) fmt = de.numbers.getFormatter(type)
return fmt.format(num) return fmt.format(num)
def toStr(value, encoding='UTF-8'):
if isinstance(value, unicode):
return value.encode(encoding)
return str(value)
def toUnicode(value, encoding='UTF-8'):
if isinstance(value, unicode):
return value
elif isinstance(value, str):
return value.decode(encoding)
else:
return u''