def applyValue(self, widget, value): """Validate and apply value to given widget. This method gets called on any ObjectWidget value change and is responsible for validating the given value and setup an error message. This is internal apply value and validation process is needed because nothing outside this widget does know something about our internal sub widgets. """ if value is not interfaces.NO_VALUE: try: # convert widget value to field value converter = interfaces.IDataConverter(widget) fvalue = converter.toFieldValue(value) # validate field value zope.component.getMultiAdapter( (self.context, self.request, self.form, getattr(widget, 'field', None), widget), interfaces.IValidator).validate(fvalue) # convert field value back to widget value # that will probably format the value too widget.value = converter.toWidgetValue(fvalue) except (zope.schema.ValidationError, ValueError) as error: # on exception, setup the widget error message view = zope.component.getMultiAdapter( (error, self.request, widget, widget.field, self.form, self.context), interfaces.IErrorViewSnippet) view.update() widget.error = view # set the wrong value as value despite it's wrong # we want to re-show wrong values widget.value = value
def updateWidgets(self): prefix = get_prefix(self) super(BookingForm, self).updateWidgets(prefix=prefix) defaults = { 'date': date.today() } text_widget = self.widgets['text'] electric_chars = { k: v for k, v in text_widget.base_electric_chars.items() } if IStory.providedBy(self.context): text_widget.base_electric_chars = elchar_strip( electric_chars, 'Project', 'Story' ) project = api.content.get_project(self.context) defaults.update({ 'references': [ ('Project', IUUID(project), True), ('Story', IUUID(self.context), True) ] }) text_widget.placeholder = _(u"*ticket #tag activity") elif IProject.providedBy(self.context): text_widget.base_electric_chars = elchar_strip( electric_chars, 'Story' ) defaults.update({ 'references': [ ('Project', IUUID(self.context), True) ] }) text_widget.placeholder = _(u"@story *ticket #tag activity") for name, widget in self.widgets.items(): if name in defaults: converter = interfaces.IDataConverter(widget) widget.value = converter.toWidgetValue(defaults[name]) if name == 'text': widget.references_field = self.widgets['references'].name widget.tags_field = self.widgets['tags'].name if name in ['references', 'tags']: widget.mode = interfaces.HIDDEN_MODE
def datagrid_field_get(self): # value (get) cannot raise an exception, then we return # insane values try: return self.extract() except MultipleErrors: value = {} active_names = self.subform.fields.keys() for name in getFieldNames(self.field.schema): if name not in active_names: continue widget = self.subform.widgets[name] widget_value = widget.value try: converter = interfaces.IDataConverter(widget) value[name] = converter.toFieldValue(widget_value) except (FormatterValidationError, ValidationError, ValueError): value[name] = widget_value return value
def _validate(self): # copied from z3c.form 3.2.10 for widget in self.widgets.values(): try: # convert widget value to field value converter = interfaces.IDataConverter(widget) value = converter.toFieldValue(widget.value) # validate field value zope.component.getMultiAdapter( (self.context, self.request, self.parentForm, getattr(widget, 'field', None), widget), interfaces.IValidator).validate(value, force=True) except (zope.schema.ValidationError, ValueError) as error: # on exception, setup the widget error message view = zope.component.getMultiAdapter( (error, self.request, widget, widget.field, self.parentForm, self.context), interfaces.IErrorViewSnippet) view.update() widget.error = view
def extract(self): """See interfaces.IWidgets""" data = {} errors = () for name, widget in self.items(): if IContentProvider.providedBy(widget): continue if widget.mode == interfaces.DISPLAY_MODE: continue value = widget.field.missing_value try: widget.setErrors = self.setErrors raw = widget.extract() if raw is not interfaces.NO_VALUE: value = interfaces.IDataConverter(widget).toFieldValue(raw) zope.component.getMultiAdapter( (self.content, self.request, self.form, getattr(widget, 'field', None), widget), interfaces.IValidator).validate(value) except (zope.interface.Invalid, ValueError, MultipleErrors) as error: view = zope.component.getMultiAdapter( (error, self.request, widget, widget.field, self.form, self.content), interfaces.IErrorViewSnippet) view.update() if self.setErrors: widget.error = view errors += (view, ) else: name = widget.__name__ data[name] = value for error in self.validate(data): view = zope.component.getMultiAdapter( (error, self.request, None, None, self.form, self.content), interfaces.IErrorViewSnippet) view.update() errors += (view, ) if self.setErrors: self.errors = errors return data, errors
def update(self): """See z3c.form.interfaces.IWidget.""" # Step 1: Determine the value. value = interfaces.NO_VALUE lookForDefault = False # Step 1.1: If possible, get a value from the request if not self.ignoreRequest: #at this turn we do not need errors to be set on widgets #errors will be set when extract gets called from form.extractData self.setErrors = False widget_value = self.extract() if widget_value is not interfaces.NO_VALUE: # Once we found the value in the request, it takes precendence # over everything and nothing else has to be done. self.value = widget_value value = PLACEHOLDER # Step 1.2: If we have a widget with a field and we have no value yet, # we have some more possible locations to get the value if (interfaces.IFieldWidget.providedBy(self) and value is interfaces.NO_VALUE and value is not PLACEHOLDER): # Step 1.2.1: If the widget knows about its context and the # context is to be used to extract a value, get # it now via a data manager. if (interfaces.IContextAware.providedBy(self) and not self.ignoreContext): value = zope.component.getMultiAdapter( (self.context, self.field), interfaces.IDataManager).query() # Step 1.2.2: If we still do not have a value, we can always use # the default value of the field, if set # NOTE: It should check field.default is not missing_value, but # that requires fixing zope.schema first # We get a clone of the field with the context binded field = self.field.bind(self.context) # PATCHED: # Only look for a default value if value is equal to missing_value # AND the field is required. Otherwise the widget might ignore # persisted, legitimate no-values for optional fields. # # (Or, as before the patch, if value is NO_VALUE - which # usually means we're in an add form). # # Based on z3c.form = 3.2.11 if (field.required and value is field.missing_value ) or value is interfaces.NO_VALUE: default_value = field.default if default_value is not None and self.showDefault: value = field.default lookForDefault = True # Step 1.3: If we still have not found a value, then we try to get it # from an attribute value if ((value is interfaces.NO_VALUE or lookForDefault) and self.showDefault): adapter = zope.component.queryMultiAdapter( (self.context, self.request, self.form, self.field, self), interfaces.IValue, name='default') if adapter: value = adapter.get() # Step 1.4: Convert the value to one that the widget can understand if value not in (interfaces.NO_VALUE, PLACEHOLDER): converter = interfaces.IDataConverter(self) self.value = converter.toWidgetValue(value) # Step 2: Update selected attributes for attrName in self._adapterValueAttributes: # only allow to set values for known attributes if hasattr(self, attrName): value = zope.component.queryMultiAdapter( (self.context, self.request, self.form, self.field, self), interfaces.IValue, name=attrName) if value is not None: setattr(self, attrName, value.get())