def update(self): """See interfaces.IWidgets""" # Create a unique prefix. prefix = util.expandPrefix(self.form.prefix) prefix += util.expandPrefix(self.prefix) # Walk through each field, making a widget out of it. uniqueOrderedKeys = [] for field in self.form.fields.values(): # Step 0. Determine whether the context should be ignored. #------------------------------------------------------------------- if self.draftable: ignoreContext = False else: ignoreContext = self.ignoreContext if field.ignoreContext is not None: ignoreContext = field.ignoreContext #------------------------------------------------------------------- # Step 1: Determine the mode of the widget. mode = self.mode if field.mode is not None: mode = field.mode elif field.field.readonly and not self.ignoreReadonly: mode = interfaces.DISPLAY_MODE elif not ignoreContext: # If we do not have enough permissions to write to the # attribute, then switch to display mode. #try: dm = zope.component.getMultiAdapter( (self.content, field.field), interfaces.IDataManager) if not dm.canWrite(): mode = interfaces.DISPLAY_MODE #except TypeError: # # If datamanager can not adapt, then we can't write and # # must ignore context (since it could not adapt) # ignoreContext = True # Step 2: Get the widget for the given field. shortName = field.__name__ newWidget = True if shortName in self._data: # reuse existing widget widget = self._data[shortName] newWidget = False elif field.widgetFactory.get(mode) is not None: factory = field.widgetFactory.get(mode) widget = factory(field.field, self.request) else: widget = zope.component.getMultiAdapter( (field.field, self.request), interfaces.IFieldWidget) # Step 2.5: If widget is draftable and no widget exists, create draft if self.draftable == False and IDraftable.providedBy(widget): proxy = zope.component.queryMultiAdapter((self.content, self.request, self.form), IZ3cFormDataContext) if proxy is not None: proxy.createDraft = True self.content = proxy.adapt() if IZ3cDraft.providedBy(self.content): self.draftable = True ignoreContext = False # Step 3: Set the prefix for the widget widget.name = prefix + shortName widget.id = (prefix + shortName).replace('.', '-') # Step 4: Set the context widget.context = self.content # Step 5: Set the form widget.form = self.form # Optimization: Set both interfaces here, rather in step 4 and 5: # ``alsoProvides`` is quite slow zope.interface.alsoProvides( widget, interfaces.IContextAware, interfaces.IFormAware) # Step 6: Set some variables widget.ignoreContext = ignoreContext widget.ignoreRequest = self.ignoreRequest # Step 7: Set the mode of the widget widget.mode = mode # Step 8: Update the widget widget.update() #------------------------------------------------------------------- # Save converted widget value on draft if it different from what is # already stored on draft if self.draftable and self.draftWritable == True and ignoreContext == False: dm = zope.component.getMultiAdapter( (self.content, field.field), interfaces.IDataManager) try: value = interfaces.IDataConverter(widget).toFieldValue(widget.value) #if getattr(self.content, field.__name__, None) != value: if dm.query() != value: dm.set(value) except ValueError: pass #------------------------------------------------------------------- zope.event.notify(AfterWidgetUpdateEvent(widget)) # Step 9: Add the widget to the manager if widget.required: self.hasRequiredFields = True uniqueOrderedKeys.append(shortName) if newWidget: self._data_values.append(widget) self._data[shortName] = widget zope.location.locate(widget, self, shortName) # allways ensure that we add all keys and keep the order given from # button items self._data_keys = uniqueOrderedKeys
def adapt(self): """If we are drafting a content item, record form data information to the draft, but read existing data from the underlying object. """ # Check to see if we have a cahced copy already if IZ3cDraft.providedBy(self.request): return self.request.DRAFT.context if IDraftable.providedBy(self.request): self.createDraft = True # Set up the draft (sets cookies, markers, etc) draft = getCurrentDraft(self.request, create=False) if not draft and not self.createDraft: return self.content if not draft: beginDrafting(self.content, self.form) draft = getCurrentDraft(self.request, create=self.createDraft) if draft is None: return self.content # return contnet, not context context = getattr(draft, 'context', None) # Initial draft; populate initial values if context is None: context = PersistentDict() # Get all fields from from, including groups so we can store them # on draft _fields = [] for field in self.form.fields.items(): _fields.append(field) if hasattr(self.form, 'groups'): for group in self.form.groups: for field in group.fields.items(): _fields.append(field) for name, field in _fields: # Provide default value on draft dm = zope.component.getMultiAdapter( (self.content, field.field), interfaces.IDataManager) try: value = dm.query(field) except TypeError: value = field.field.default or field.field.missing_value context[field.field.__name__] = value zope.interface.alsoProvides(context, IZ3cDraft) zope.interface.alsoProvides(context, IDrafting) setattr(draft, 'context', context) zope.interface.alsoProvides(draft, IZ3cDraft) zope.interface.alsoProvides(self.request, IZ3cDraft) # Cache draft self.request['DRAFT'] = draft return context