improvements and fixes of form validation

git-svn-id: svn://svn.cy55.de/Zope3/src/cybertools/trunk@1969 fd906abe-77d9-0310-91a1-e0d9ade77398
This commit is contained in:
helmutm 2007-08-29 15:34:18 +00:00
parent 1e1feb6fd5
commit 18ea13f7b8
5 changed files with 71 additions and 32 deletions

View file

@ -28,11 +28,12 @@ from zope.cachedescriptors.property import Lazy
from cybertools.composer.schema.browser.common import BaseView from cybertools.composer.schema.browser.common import BaseView
from cybertools.composer.interfaces import IInstance from cybertools.composer.interfaces import IInstance
from cybertools.composer.schema.interfaces import IClientFactory from cybertools.composer.schema.interfaces import IClientFactory
from cybertools.composer.schema.schema import FormState
class SchemaView(BaseView): class SchemaView(BaseView):
formState = None formState = FormState()
@Lazy @Lazy
def fields(self): def fields(self):
@ -55,10 +56,15 @@ class SchemaView(BaseView):
return {} return {}
instance = IInstance(client) instance = IInstance(client)
instance.template = self.context instance.template = self.context
return instance.applyTemplate() data = instance.applyTemplate(mode='edit')
# TODO: overwrite data with values from form for k, v in data.items():
#overwrite data with values from form
if k in form:
data[k] = form[k]
return data
def update(self): def update(self):
newClient = False
form = self.request.form form = self.request.form
if not self.clientName: if not self.clientName:
self.clientName = form.get('id') self.clientName = form.get('id')
@ -69,19 +75,21 @@ class SchemaView(BaseView):
if clientName: if clientName:
client = manager.getClients().get(clientName) client = manager.getClients().get(clientName)
if client is None: if client is None:
# no valid clientName - show empty form
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) # only add client to manager after validation, so we have
# to keep the info about new client here
newClient = True
instance = component.getAdapter(client, IInstance, name='editor') instance = component.getAdapter(client, IInstance, name='editor')
instance.template = self.context instance.template = self.context
self.formState = formState = instance.applyTemplate(form) self.formState = formState = instance.applyTemplate(form)
if formState.severity > 0: if formState.severity > 0:
# show form again # show form again; do not add client to manager
return True return True
if newClient:
clientName = self.clientName = manager.addClient(client)
self.request.response.redirect(self.nextUrl()) self.request.response.redirect(self.nextUrl())
return False return False

View file

@ -23,10 +23,10 @@ $Id$
""" """
from zope.interface import implements from zope.interface import implements
from zope import schema
from cybertools.composer.base import Component from cybertools.composer.base import Component
from cybertools.composer.schema.interfaces import IField, IFieldState from cybertools.composer.schema.interfaces import IField, IFieldState
from cybertools.composer.schema.schema import formErrors
from cybertools.util.format import toStr, toUnicode from cybertools.util.format import toStr, toUnicode
@ -53,23 +53,24 @@ class Field(Component):
def getTitleValue(self): def getTitleValue(self):
return self.title or self.name return self.title or self.name
def marshallValue(self, value): def marshall(self, value):
return value return value
#return toStr(value) #return toStr(value)
def displayValue(self, value): def display(self, value):
return value return value
#return toStr(value) #return toStr(value)
def unmarshallValue(self, strValue): def unmarshall(self, strValue):
return toUnicode(strValue) or u'' return toUnicode(strValue) or u''
def validateValue(self, value): def validateValue(self, value):
errors = [] errors = []
severity = 0 severity = 0
if not value and self.required: if not value and self.required:
errors.append('required_missing') error = formErrors['required_missing']
severity = 5 errors.append(error)
severity = error.severity
return FieldState(self.name, errors, severity) return FieldState(self.name, errors, severity)

View file

@ -67,6 +67,7 @@ class ClientInstance(object):
to the corresponding values from the context object. to the corresponding values from the context object.
""" """
result = {} result = {}
mode = kw.get('mode', 'view')
attrs = getattr(self.context, self.attrsName, None) attrs = getattr(self.context, self.attrsName, None)
if attrs is None: if attrs is None:
return result return result
@ -75,7 +76,9 @@ class ClientInstance(object):
if template is not None: if template is not None:
for f in template.fields: for f in template.fields:
name = f.name name = f.name
result[name] = f.displayValue(values.get(name, u'')) value = values.get(name, u'')
value = mode == 'view' and f.display(value) or f.marshall(value)
result[name] = value
result['__name__'] = self.context.__name__ result['__name__'] = self.context.__name__
return result return result
@ -87,25 +90,36 @@ class ClientInstanceEditor(ClientInstance):
using corresponding values from the data argument. using corresponding values from the data argument.
Return the resulting form state (an object providing IFormState). Return the resulting form state (an object providing IFormState).
""" """
formState = FormState() template = self.template
if template is None:
return FormState()
formState = self.validate(data)
if formState.severity > 0:
# don't do anything if there is an error
return 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()
setattr(self.context, self.attrsName, attrs) setattr(self.context, self.attrsName, attrs)
template = self.template
values = attrs.setdefault(self.aspect, OOBTree()) values = attrs.setdefault(self.aspect, OOBTree())
if template is not None: for f in template.fields:
for f in template.fields: name = f.name
name = f.name fieldState = formState.fieldStates[name]
value = f.unmarshallValue(data.get(name)) value = f.unmarshall(data.get(name))
fieldState = f.validateValue(value) if name in data:
if name in data: oldValue = values.get(name)
oldValue = values.get(name) if value != oldValue:
if value != oldValue: values[name] = value
values[name] = value fieldState.change = (oldValue, value)
fieldState.change = (oldValue, value) formState.changed = True
formState.changed = True return formState
formState.fieldStates.append(fieldState)
formState.severity = max(formState.severity, fieldState.severity) def validate(self, data):
formState = FormState()
for f in self.template.fields:
value = f.unmarshall(data.get(f.name))
fieldState = f.validateValue(value)
formState.fieldStates.append(fieldState)
formState.severity = max(formState.severity, fieldState.severity)
return formState return formState

View file

@ -78,7 +78,8 @@ 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', 'checkbox')) values=('textline', 'textarea', 'number',
'date', 'checkbox', 'spacer'))
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'),
@ -177,4 +178,3 @@ class IClientManager(Interface):
""" Add the client object given to the collection of clients. """ Add the client object given to the collection of clients.
""" """

View file

@ -69,3 +69,19 @@ class FormState(object):
self.changed = changed self.changed = changed
self.severity = severity self.severity = severity
class FormError(object):
def __init__(self, title, description=None, severity=5):
self.title = title
self.description = description or title
self.severity = severity
def __str__(self):
return self.title
formErrors = dict(
required_missing=FormError(u'Missing data for required field',
u'Please enter data for required field.')
)