class FormData(Object): """This represent a submission of a form. It can be used to update widgets and run actions. """ prefix = 'form' parent = None mode = INPUT dataManager = ObjectDataManager dataValidators = [] postOnly = True formMethod = 'post' enctype = 'multipart/form-data' ignoreRequest = False ignoreContent = True status = u'' def __init__(self, context, request, content=_marker): super(FormData, self).__init__(context, request) self.context = context self.request = request self.errors = Errors() # This should move to FormCanvas self._extracted = {} self.__content = None if content is _marker: content = context self.setContentData(content) @property def formErrors(self): error = self.errors.get(self.prefix, None) if self.errors and error is None: # If the form has errors but no form specific ones # we have to add it. This could be overridable. error = Error(_(u"There were errors."), self.prefix) if error is not None: # If there's a form error, we need to make sure it's iterable. # Doing this, we can handle both Error and Errors. # Some forms can trigger more than one error, on failure. if ICollection.providedBy(error): return error else: return [error] return [] def htmlId(self): return self.prefix.replace('.', '-') def getContent(self): # Shortcut for actions. You should not reimplement that method # but getContentData. return self.getContentData().getContent() def getContentData(self): return self.__content def setContentData(self, content): if not interfaces.IDataManager.providedBy(content): content = self.dataManager(content) self.__content = content def validateData(self, fields, data): errors = Errors() for factory in self.dataValidators: validator = factory(fields, self) for error in validator.validate(data): errors.append(Error(error.args[0], self.prefix)) return errors @cached('_extracted') def extractData(self, fields): data = FieldsValues(self, fields) errors = Errors() for field in fields: if not field.available(self): continue # Widget extraction and validation extractor = getWidgetExtractor(field, self, self.request) if extractor is not None: value, error = extractor.extract() if error is None: error = field.validate(value, self.context) if error is not None: if not interfaces.IError.providedBy(error): if interfaces.IErrors.providedBy(error): # this is an Errors, not implementing IError # "Make it so, number one !" error = Errors( *error, identifier=extractor.identifier) else: error = Error( error, identifier=extractor.identifier) errors.append(error) data[field.identifier] = value # Generic form validation validation_errors = self.validateData(fields, data) errors.extend(validation_errors) self.errors = errors return (data, errors)
class FormData(Object): """This represent a submission of a form. It can be used to update widgets and run actions. """ prefix = 'form' parent = None mode = INPUT dataManager = ObjectDataManager widgetFactoryFactory = WidgetFactory dataValidators = [] formMethod = 'POST' enctype = 'multipart/form-data' methods = frozenset(('POST', 'GET')) ignoreRequest = False ignoreContent = True status = u'' def __init__(self, context, request, content=_marker): super(FormData, self).__init__(context, request) self.context = context self.request = request self.errors = Errors() # This should move to FormCanvas self._extracted = {} self.__content = None if content is _marker: content = context self.setContentData(content) @Lazy def widgetFactory(self): return self.widgetFactoryFactory(self, self.request) @property def formErrors(self): error = self.errors.get(self.prefix, None) if error is None: return [] if ICollection.providedBy(error): return error return [error] def htmlId(self): return self.prefix.replace('.', '-') def getContent(self): # Shortcut for actions. You should not reimplement that method # but getContentData. return self.getContentData().getContent() def getContentData(self): return self.__content def setContentData(self, content): if not interfaces.IDataManager.providedBy(content): content = self.dataManager(content) self.__content = content def validateData(self, fields, data): errors = Errors() for factory in self.dataValidators: validator = factory(fields, self) for error in validator.validate(data): if not IError.providedBy(error): error = Error(error, self.prefix) errors.append(error) return errors @cached('_extracted') def extractData(self, fields): # XXX to review this cached = self._extracted.get(fields) if cached is not None: return cached data = FieldsValues(self, fields) errors = Errors() self._extracted[fields] = (data, errors) for field in fields: if not field.available(self): continue # Widget extraction and validation extractor = self.widgetFactory.extractor(field) if extractor is not None: value, error = extractor.extract() if error is None: error = field.validate(value, self) if error is not None: if not IError.providedBy(error): error = Error(error, extractor.identifier) errors.append(error) data[field.identifier] = value # Generic form validation errors.extend(self.validateData(fields, data)) if len(errors): # Add a form level error if not already present if self.prefix not in errors: errors.append( Error(_(u"There were errors.", default=u"There were errors."), self.prefix)) self.errors = errors return (data, errors)