class INameTokenTableRowSchema(Interface): """Schema for dict rows used in DataGridFields name is the 'real' name token is the token used in the vocabularies """ name = schema.TextLine(title=_(u"Name")) token = schema.TextLine(title=_(u"Token"))
class IPerson(model.Schema, IContactContent): """Interface for Person content type""" is_created = Attribute(u"Marker to know if the object is already created") lastname = schema.TextLine( title=_("Lastname"), required=True ) firstname = schema.TextLine( title=_("Firstname"), required=False, ) gender = schema.Choice( title=_("Gender"), vocabulary="Genders", required=False, ) form.widget(gender=RadioFieldWidget) person_title = schema.TextLine( title=_("Person title"), required=False, ) photo = NamedImage( title=_("Photo"), required=False, ) def get_held_positions(self): """Returns held positions of this person
class AddOrganization(form.AddForm): implements(IFieldsAndContentProvidersForm) contentProviders = ContentProviders(['organization-ms']) contentProviders['organization-ms'].position = 2 label = _(u"Create ${name}", mapping={'name': _(u"organization/position")}) description = u"" prefix = 'oform' fields = field.Fields(IAddContact).select('organization', 'position') def updateWidgets(self): super(AddOrganization, self).updateWidgets() self.widgets['organization'].label = _( 'help_add_organization_or_position_organization', "Please fill the organization first " "and then eventually select position") @button.buttonAndHandler(_('Add'), name='save') def handleAdd(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return self._finishedAdd = True if data['position'] is not None: self.request.response.redirect(data['position'].absolute_url()) return elif data['organization'] is not None: self.request.response.redirect(data['organization'].absolute_url()) return @button.buttonAndHandler(DMF(u'Cancel'), name='cancel') def handleCancel(self, action): pass
def render(self): request = self.request request.response.setHeader('Content-Type', 'application/json') return json.dumps({ 'M': translate(_(u"Mr"), context=request), 'F': translate(_(u"Mrs"), context=request), })
def render(self): request = self.request request.response.setHeader( 'Content-Type', 'application/json') return json.dumps({ 'M': translate(_(u"Mr"), context=request), 'F': translate(_(u"Mrs"), context=request), })
class IContactCoreParameters(Interface): person_title_in_title = schema.Bool( title=_(u"Display person title in displayed person's title."), description=u"", required=False, default=True) use_held_positions_to_search_person = schema.Bool( title=_(u"Use held positions to search persons."), description=u"", required=False, default=True)
class IAddContact(model.Schema): organization = ContactChoice( title=_(u"Organization"), required=False, source=ContactSourceBinder(portal_type="organization")) person = ContactChoice(title=_(u"Person"), required=False, source=ContactSourceBinder(portal_type="person")) position = ContactChoice( title=_(u"Position"), required=False, source=ContactSourceBinder(portal_type="position"))
class IOrganization(model.Schema, IContactContent): """Interface for Organization content type""" activity = RichText( title=_("Activity"), required=False, ) organization_type = schema.Choice( title=_("Type or level"), vocabulary="OrganizationTypesOrLevels", ) logo = NamedImage( title=_("Logo"), required=False, ) def get_organizations_chain(self): """Returns the list of organizations and sub-organizations in this organization e.g. for HR service in Division Bar in Organization Foo : [OrganizationFoo, DivisionBar, HRService] """ def get_root_organization(self): """Returns the first organization in the chain e.g. the company or the institution """ def get_organizations_titles(self): """Returns the list of titles of the organizations and sub-organizations in this organization e.g. for HR service in Division Bar in Organization Foo : ["Organization Foo", "Division Bar", "HR service"] """ def get_full_title(self): """Returns the full title of the organization It is constituted by the list of the names of the organizations and sub-organizations in this organization separated by slashes e.g. for HR service in Division Bar in Organization Foo : u"Organization Foo / Division Bar / HR service" """ def get_positions(self): """Returns the positions""" def get_held_positions(self): """Returns the held positions
class IBirthday(model.Schema): form.widget(birthday=DateFieldWidget) birthday = schema.Date( title=_("Birthday"), required=False, )
class IContactCoreParameters(Interface): person_title_in_title = schema.Bool( title=_(u"Display person title in displayed person's title."), description=u"", required=False, default=True)
class IRelatedOrganizations(model.Schema): """A content on which we can attach organizations """ fieldset( 'related_organizations', label=_(u'Related organizations'), fields=('related_organizations',), ) related_organizations = ContactList( value_type=ContactChoice( description=_("Search and attach organizations related to this one"), source=ContactSourceBinder(portal_type=("organization",)),), required=False, addlink=False, )
def label_for_portal_type(self, portal_type): if isinstance(portal_type, Message): type_name = portal_type else: fti = getUtility(IDexterityFTI, name=portal_type) type_name = fti.Title() label = _(u"Create ${name}", mapping={'name': type_name}) return label
class IHeldPosition(model.Schema, IContactContent): """Interface for HeldPosition content type""" position = ContactChoice( title=_("Organization/Position"), source=ContactSourceBinder(portal_type=("organization", "position")), required=True, ) label = schema.TextLine(title=_("Additional label"), description=_("Additional label with information that does not appear on position label"), required=False) start_date = schema.Date( title=_("Start date"), required=False, ) end_date = schema.Date( title=_("End date"), required=False, ) photo = NamedImage( title=_("Photo"), required=False, readonly=True, ) def get_person(): """Returns the person who holds the position """ def get_position(): """Returns the position (if position field is a position) """ def get_organization(): """Returns the first organization related to HeldPosition
class IAddContact(model.Schema): """Schema to add held position, person or organization Fields are not required.""" organization = ContactChoice( title=_(u"Organization"), required=False, description=_( u"Select the organization where the person holds the position"), source=ContactSourceBinder(portal_type="organization")) person = ContactChoice( title=_(u"Person"), description=_(u"Select the person who holds the position"), required=False, source=ContactSourceBinder(portal_type="person")) position = ContactChoice( title=_(u"Position"), required=False, description= _(u"Select the position held by this person in the selected organization" ), source=ContactSourceBinder(portal_type="position"))
class IPosition(model.Schema, IContactContent): """Interface for Position content type""" position_type = schema.Choice( title=_("Type"), vocabulary="PositionTypes", ) def get_organization(self): """Returns the organization to which the position is linked""" def get_full_title(self): """Returns the full title of the position
class IGlobalPositioning(model.Schema): """GlobalPositioning behavior""" fieldset('global_positioning', label=_(u'Global positioning'), fields=('latitude', 'longitude')) latitude = schema.Float( title=_('Latitude'), description=_('Latitude'), min=-90.0, max=90.0, required=False, ) longitude = schema.Float( title=_('Longitude'), description=_('Longitude'), min=-90.0, max=90.0, required=False, )
class IDirectory(model.Schema): """Interface for Directory content type""" position_types = schema.List(title=_("Position types"), value_type=DictRow( title=_(u'Position'), schema=INameTokenTableRowSchema)) widget(position_types=DataGridFieldFactory) organization_types = schema.List(title=_("Organization types"), value_type=DictRow( title=_(u'Organization'), schema=INameTokenTableRowSchema)) widget(organization_types=DataGridFieldFactory) organization_levels = schema.List(title=_("Organization levels"), value_type=DictRow( title=_(u'Organization level'), schema=INameTokenTableRowSchema)) widget(organization_levels=DataGridFieldFactory)
def prelabel_for_portal_type(self, portal_type): return _( 'help_widget_add_new_elt', default="If the item doesn't exist, you can add it to the database :")
def add_contact_infos(self, widget): source = widget.bound_source criteria = source.selectable_filter.criteria addlink_enabled = widget.field.addlink portal_types = criteria.get('portal_type', []) catalog = getToolByName(widget.context, 'portal_catalog') results = catalog.unrestrictedSearchResults(portal_type='directory') actions = [] if len(results) == 0: addlink_enabled = False else: directory = results[0].getObject() sm = getSecurityManager() if not sm.checkPermission("Add portal content", directory): addlink_enabled = False close_on_click = True if addlink_enabled: directory_url = directory.absolute_url() if len(portal_types) == 1: portal_type = portal_types[0] if portal_type == 'held_position' and not IPerson.providedBy( widget.context): url = "%s/@@add-contact" % directory_url type_name = _(u"Contact") label = _(u"Create ${name}", mapping={'name': type_name}) if getattr(source, 'relations', None): # if we have a relation, with an organization or a position # we will pre-complete contact creation form if 'position' in source.relations: related_path = source.relations['position'] related_to = api.content.get(related_path) label = _(u"Create ${name} (${position})", mapping={ 'name': type_name, 'position': related_to.Title() }) url += '?oform.widgets.%s=%s' % ( related_to.portal_type, '/'.join( related_to.getPhysicalPath())) action = { 'url': url, 'label': label, 'klass': 'addnew', 'formselector': '#oform', 'closeselector': '[name="oform.buttons.cancel"]' } actions.append(action) close_on_click = False else: custom_settings = queryAdapter(directory, ICustomSettings, default=self) url = custom_settings.add_url_for_portal_type( directory_url, portal_type) fti = getUtility(IDexterityFTI, name=portal_type) type_name = fti.Title() label = _(u"Create ${name}", mapping={'name': type_name}) action = {'url': url, 'label': label} actions.append(action) else: if len(portal_types) == 2 and \ 'organization' in portal_types and \ 'position' in portal_types: url = "%s/@@add-organization" % directory_url type_name = _(u"organization/position") else: url = "%s/@@add-contact" % directory_url type_name = _(u"Contact") close_on_click = False label = _(u"Create ${name}", mapping={'name': type_name}) action = { 'url': url, 'label': label, 'klass': 'addnew', 'formselector': '#oform', 'closeselector': '[name="oform.buttons.cancel"]' } actions.append(action) return { 'actions': actions, 'close_on_click': close_on_click, 'formatItem': """function(row, idx, count, value) { return '<img src="' + portal_url + '/' + row[2] + '_icon.png' +'" /> ' + row[1] }""" }
def updateWidgets(self): super(AddOrganization, self).updateWidgets() self.widgets['organization'].label = _( 'help_add_organization_or_position_organization', "Please fill the organization first " "and then eventually select position")
def add_contact_infos(self, widget): source = widget.bound_source criteria = source.selectable_filter.criteria addlink_enabled = widget.field.addlink portal_types = criteria.get('portal_type', []) catalog = api.portal.get_tool('portal_catalog') results = catalog.unrestrictedSearchResults(portal_type='directory') actions = [] if len(results) == 0: addlink_enabled = False else: directory = results[0].getObject() sm = getSecurityManager() if not sm.checkPermission("Add portal content", directory): addlink_enabled = False close_on_click = True custom_settings = queryAdapter(directory, ICustomSettings, default=self) if addlink_enabled: directory_url = directory.absolute_url() if len(portal_types) == 1: portal_type = portal_types[0] prelabel = custom_settings.prelabel_for_portal_type(portal_type) if portal_type == 'held_position' and not IPerson.providedBy(widget.context): url = "%s/@@add-held-position" % directory_url type_name = _(u"Contact") label = custom_settings.label_for_portal_type(type_name) if getattr(source, 'relations', None): # if we have a relation, with an organization or a position # we will pre-complete contact creation form if 'position' in source.relations: related_path = source.relations['position'] related_to = api.content.get(related_path) if related_to is not None: type_name = _( "${name} (${position}", mapping={'name': type_name, 'position': related_to.Title()}) label = custom_settings.label_for_portal_type(type_name) url += '?oform.widgets.%s=%s' % (related_to.portal_type, '/'.join(related_to.getPhysicalPath())) action = {'url': url, 'label': label, 'prelabel': prelabel, 'klass': 'addnew', 'formselector': '#oform', 'closeselector': '[name="oform.buttons.cancel"]'} actions.append(action) close_on_click = False else: label = custom_settings.label_for_portal_type(portal_type) url = custom_settings.add_url_for_portal_type(directory_url, portal_type) action = { 'url': url, 'label': label, 'prelabel': prelabel, } actions.append(action) else: if len(portal_types) == 2 and \ 'organization' in portal_types and \ 'position' in portal_types: url = "%s/@@add-organization" % directory_url type_name = _(u"organization/position") else: url = "%s/@@add-contact" % directory_url type_name = _(u"Contact") close_on_click = False label = custom_settings.label_for_portal_type(type_name) prelabel = custom_settings.prelabel_for_portal_type(portal_types) action = {'url': url, 'klass': 'addnew', 'label': label, 'prelabel': prelabel, 'formselector': '#oform', 'closeselector': '[name="oform.buttons.cancel"]'} actions.append(action) return {'actions': actions, 'close_on_click': close_on_click, 'formatItem': """function(row, idx, count, value) { return '<img src="' + portal_url + '/' + row[2] + '_icon.png' +'" /> ' + row[1] }""" }
class AddContact(DefaultAddForm, form.AddForm): implements(IFieldsAndContentProvidersForm) contentProviders = ContentProviders(['organization-ms']) # contentProviders['organization-ms'] = MasterSelectAddContactProvider contentProviders['organization-ms'].position = -1 label = _(u"Create ${name}", mapping={'name': _(u"Contact")}) description = _( u"A contact is a position held by a person in an organization") schema = IAddContact portal_type = 'held_position' prefix = 'oform' @property def additionalSchemata(self): fti = getUtility(IDexterityFTI, name=self.portal_type) schema = fti.lookupSchema() # save the schema name to be able to remove a field afterwards self._schema_name = schema.__name__ return (schema, ) def updateFieldsFromSchemata(self): super(AddContact, self).updateFieldsFromSchemata() # IHeldPosition and IAddContact have both a field named position # hide the one from IHeldPosition # TODO: there is no hidden template for autocomplete widget, # we hide it in javascript for now. self.fields[self._schema_name + '.position'].mode = HIDDEN_MODE hp_fti = api.portal.get_tool('portal_types').held_position if IContactDetails.__identifier__ in hp_fti.behaviors: self.fields += field.Fields(IContactDetails) def updateWidgets(self): super(AddContact, self).updateWidgets() for widget in self.widgets.values(): if getattr(widget, 'required', False): # This is really a hack to not have required field errors # but have the visual required nevertheless. # We need to revert this after updateActions # because this change impact the held position form widget.field.required = False if 'parent_address' in self.widgets: self.widgets['parent_address'].mode = DISPLAY_MODE def update(self): super(AddContact, self).update() # revert required field changes for widget in self.widgets.values(): if getattr(widget, 'required', False): widget.field.required = True @button.buttonAndHandler(_('Add'), name='save') def handleAdd(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return obj = self.createAndAdd(data) if obj is not None: # mark only as finished if we get the new object self._finishedAdd = True IStatusMessage(self.request).addStatusMessage( DMF(u"Item created"), "info") @button.buttonAndHandler(DMF(u'Cancel'), name='cancel') def handleCancel(self, action): IStatusMessage(self.request).addStatusMessage( DMF(u"Add New Item operation cancelled"), "info") self.request.response.redirect(self.nextURL()) notify(AddCancelledEvent(self.context)) def createAndAdd(self, data): if data['person'] is None and data['organization'] is None: return elif data['organization'] is not None and data['person'] is None: self.request.response.redirect(data['organization'].absolute_url()) self._finishedAdd = True return elif data['person'] is not None and data['organization'] is None: self.request.response.redirect(data['person'].absolute_url()) self._finishedAdd = True return else: return super(AddContact, self).createAndAdd(data) def create(self, data): self._container = data.pop('person') position = data.pop('position') orga = data.pop('organization') if position is None: position = orga data[self._schema_name + '.position'] = position return super(AddContact, self).create(data) def add(self, obj): container = self._container fti = getUtility(IDexterityFTI, name=self.portal_type) new_object = addContentToContainer(container, obj) if fti.immediate_view: self.immediate_view = "%s/%s/%s" % ( container.absolute_url(), new_object.id, fti.immediate_view, ) else: self.immediate_view = "%s/%s" % (container.absolute_url(), new_object.id)
class IContactDetails(model.Schema): """Contact details behavior""" form.write_permission( use_parent_address='collective.contact.core.UseParentAddress') fieldset('contact_details', label=_(u'Contact details'), fields=CONTACT_DETAILS_FIELDS) fieldset('address', label=_(u'Address'), fields=ADDRESS_FIELDS_PLUS_PARENT) email = schema.TextLine( title=_(u"Email"), constraint=validateEmail, required=False, ) phone = schema.TextLine( title=_(u"Phone"), required=False, constraint=validatePhone, ) cell_phone = schema.TextLine( title=_(u"Cell phone"), required=False, ) fax = schema.TextLine( title=_(u"Fax"), required=False, ) website = schema.TextLine( title=_(u"Website"), required=False, ) im_handle = schema.TextLine( title=_('Instant messenger handle'), required=False, ) use_parent_address = MasterSelectBoolField( title=_("Use the belonging entity address"), slave_fields=( { 'masterSelector': '#form-widgets-IContactDetails-use_parent_address-0, #oform-widgets-use_parent_address-0', 'name': 'country', 'action': 'show', 'hide_values': 0, 'siblings': True, }, { 'masterSelector': '#form-widgets-IContactDetails-use_parent_address-0, #oform-widgets-use_parent_address-0', 'name': 'region', 'action': 'show', 'hide_values': 0, 'siblings': True, }, { 'masterSelector': '#form-widgets-IContactDetails-use_parent_address-0, #oform-widgets-use_parent_address-0', 'name': 'zip_code', 'action': 'show', 'hide_values': 0, 'siblings': True, }, { 'masterSelector': '#form-widgets-IContactDetails-use_parent_address-0, #oform-widgets-use_parent_address-0', 'name': 'city', 'action': 'show', 'hide_values': 0, 'siblings': True, }, { 'masterSelector': '#form-widgets-IContactDetails-use_parent_address-0, #oform-widgets-use_parent_address-0', 'name': 'number', 'action': 'show', 'hide_values': 0, 'siblings': True, }, { 'masterSelector': '#form-widgets-IContactDetails-use_parent_address-0, #oform-widgets-use_parent_address-0', 'name': 'street', 'action': 'show', 'hide_values': 0, 'siblings': True, }, { 'masterSelector': '#form-widgets-IContactDetails-use_parent_address-0, #oform-widgets-use_parent_address-0', 'name': 'additional_address_details', 'action': 'show', 'hide_values': 0, 'siblings': True, }, { 'masterSelector': '#form-widgets-IContactDetails-use_parent_address-0, #oform-widgets-use_parent_address-0', 'name': 'parent_address', 'action': 'hide', 'hide_values': 0, 'siblings': True, }, ), default=True, required=False, ) parent_address = RichText( default_mime_type='text/html', output_mime_type='text/html', required=False, ) form.mode(parent_address='display') country = schema.TextLine( title=_('Country'), required=False, ) zip_code = schema.TextLine( title=_('Zip Code'), required=False, ) city = schema.TextLine( title=_('City'), required=False, ) street = schema.TextLine( title=_('Street'), required=False, ) number = schema.TextLine( title=_('Number'), required=False, ) region = schema.TextLine( title=_('Region'), required=False, ) additional_address_details = schema.TextLine( title=_('Additional address details'), required=False, )
class InvalidEmailAddress(schema.ValidationError): """Exception for invalid address""" __doc__ = _(u"Invalid email address")
def add_contact_infos(self, widget): source = widget.bound_source criteria = source.selectable_filter.criteria addlink_enabled = widget.field.addlink portal_types = criteria.get('portal_type', []) catalog = getToolByName(widget.context, 'portal_catalog') results = catalog.unrestrictedSearchResults(portal_type='directory') actions = [] if len(results) == 0: addlink_enabled = False else: directory = results[0].getObject() sm = getSecurityManager() if not sm.checkPermission("Add portal content", directory): addlink_enabled = False close_on_click = True if addlink_enabled: directory_url = directory.absolute_url() if len(portal_types) == 1: portal_type = portal_types[0] if portal_type == 'held_position' and not IPerson.providedBy( widget.context): url = "%s/@@add-contact" % directory_url type_name = _(u"Contact") label = _(u"Create ${name}", mapping={'name': type_name}) action = { 'url': url, 'label': label, 'klass': 'addnew', 'formselector': '#oform', 'closeselector': '[name="oform.buttons.cancel"]' } actions.append(action) close_on_click = False else: url = '%s/++add++%s' % (directory_url, portal_type) fti = getUtility(IDexterityFTI, name=portal_type) type_name = fti.Title() label = _(u"Create ${name}", mapping={'name': type_name}) action = {'url': url, 'label': label} actions.append(action) else: if len(portal_types) == 2 and \ 'organization' in portal_types and \ 'position' in portal_types: url = "%s/@@add-organization" % directory_url type_name = _(u"organization/position") else: url = "%s/@@add-contact" % directory_url type_name = _(u"Contact") close_on_click = False label = _(u"Create ${name}", mapping={'name': type_name}) action = { 'url': url, 'label': label, 'klass': 'addnew', 'formselector': '#oform', 'closeselector': '[name="oform.buttons.cancel"]' } actions.append(action) return { 'actions': actions, 'close_on_click': close_on_click, 'formatItem': """function(row, idx, count, value) { return '<img src="' + portal_url + '/' + row[2] + '_icon.png' +'" /> ' + row[1] }""" }
class InvalidPhone(schema.ValidationError): """Exception for invalid address""" __doc__ = _(u"Invalid phone")
def prelabel_for_portal_type(self, portal_type): return _('help_widget_add_new_elt', default= "If the item doesn't exist, you can add it to the database :")
def add_contact_infos(self, widget): source = widget.bound_source criteria = source.selectable_filter.criteria addlink_enabled = widget.field.addlink portal_types = criteria.get('portal_type', []) catalog = getToolByName(widget.context, 'portal_catalog') results = catalog.unrestrictedSearchResults(portal_type='directory') actions = [] if len(results) == 0: addlink_enabled = False else: directory = results[0].getObject() sm = getSecurityManager() if not sm.checkPermission("Add portal content", directory): addlink_enabled = False close_on_click = True if addlink_enabled: directory_url = directory.absolute_url() if len(portal_types) == 1: portal_type = portal_types[0] if portal_type == 'held_position' and not IPerson.providedBy(widget.context): url = "%s/@@add-contact" % directory_url type_name = _(u"Contact") label = _(u"Create ${name}", mapping={'name': type_name}) action = {'url': url, 'label': label, 'klass': 'addnew', 'formselector' : '#oform', 'closeselector': '[name="oform.buttons.cancel"]'} actions.append(action) close_on_click = False else: custom_settings = queryAdapter(directory, ICustomSettings, default=self) url = custom_settings.add_url_for_portal_type(directory_url, portal_type) fti = getUtility(IDexterityFTI, name=portal_type) type_name = fti.Title() label = _(u"Create ${name}", mapping={'name': type_name}) action = {'url': url, 'label': label} actions.append(action) else: if len(portal_types) == 2 and \ 'organization' in portal_types and \ 'position' in portal_types: url = "%s/@@add-organization" % directory_url type_name = _(u"organization/position") else: url = "%s/@@add-contact" % directory_url type_name = _(u"Contact") close_on_click = False label = _(u"Create ${name}", mapping={'name': type_name}) action = {'url': url, 'label': label, 'klass': 'addnew', 'formselector' : '#oform', 'closeselector': '[name="oform.buttons.cancel"]'} actions.append(action) return {'actions': actions, 'close_on_click': close_on_click, 'formatItem': """function(row, idx, count, value) { return '<img src="' + portal_url + '/' + row[2] + '_icon.png' +'" /> ' + row[1] }""" }
class AddContact(DefaultAddForm, form.AddForm): """ The following is possible with this AddContact form: - Returning a contact (held position) when you select an organization and a person. - Returning a person when you select only a person - Returning a organization when you select only an organization. It's for this case we want no required errors in the form if the IHeldPosition required fields are not filled. """ implements(IFieldsAndContentProvidersForm) contentProviders = ContentProviders(['organization-ms']) # contentProviders['organization-ms'] = MasterSelectAddContactProvider contentProviders['organization-ms'].position = -1 label = _(u"Create ${name}", mapping={'name': _(u"Contact")}) description = _( u"A contact is a position held by a person in an organization") schema = IAddContact portal_type = 'held_position' prefix = 'oform' allow_prefill_from_GET_request = True @property def additionalSchemata(self): fti = getUtility(IDexterityFTI, name=self.portal_type) schema = fti.lookupSchema() # save the schema name to be able to remove a field afterwards self._schema_name = schema.__name__ return (schema, ) def updateFieldsFromSchemata(self): super(AddContact, self).updateFieldsFromSchemata() hp_fti = api.portal.get_tool('portal_types').held_position if IContactDetails.__identifier__ in hp_fti.behaviors: self.fields += field.Fields(IContactDetails) def updateWidgets(self): super(AddContact, self).updateWidgets() # IHeldPosition and IAddContact have both a field named position # del the widget of the one from IHeldPosition but keep its field del self.widgets[self._schema_name + '.position'] if self.schema != IAddHeldPosition: for widget in self.widgets.values(): if getattr(widget, 'required', False): # copy field to not modify original one widget.field = copy.copy(widget.field) widget.field.required = False if 'parent_address' in self.widgets: self.widgets['parent_address'].mode = DISPLAY_MODE def update(self): super(AddContact, self).update() @button.buttonAndHandler(_('Add'), name='save') def handleAdd(self, action): data, errors = self.extractData() if errors: self.status = self.formErrorsMessage return obj = self.createAndAdd(data) if obj is not None: # mark only as finished if we get the new object self._finishedAdd = True IStatusMessage(self.request).addStatusMessage( DMF(u"Item created"), "info") @button.buttonAndHandler(DMF(u'Cancel'), name='cancel') def handleCancel(self, action): IStatusMessage(self.request).addStatusMessage( DMF(u"Add New Item operation cancelled"), "info") self.request.response.redirect(self.nextURL()) notify(AddCancelledEvent(self.context)) def createAndAdd(self, data): if data['person'] is None and data['organization'] is None: return elif data['organization'] is not None and data['person'] is None: self.request.response.redirect(data['organization'].absolute_url()) self._finishedAdd = True return elif data['person'] is not None and data['organization'] is None: self.request.response.redirect(data['person'].absolute_url()) self._finishedAdd = True return else: return super(AddContact, self).createAndAdd(data) def create(self, data): self._container = data.pop('person') position = data.pop('position') orga = data.pop('organization') if position is None: position = orga data[self._schema_name + '.position'] = position return super(AddContact, self).create(data) def add(self, obj): container = self._container fti = getUtility(IDexterityFTI, name=self.portal_type) new_object = addContentToContainer(container, obj) if fti.immediate_view: self.immediate_view = "%s/%s/%s" % ( container.absolute_url(), new_object.id, fti.immediate_view, ) else: self.immediate_view = "%s/%s" % (container.absolute_url(), new_object.id)