def add_fields(fields_properties, strategy, meta_required_keys, meta_optional_keys, choices_required_keys, choices_optional_keys): """ The `fields` parameter expects a list of tuples, each containing the following values: (field name, field path, widget path) For instance: [("Horizontal slider", "forms.IntegerField", "custom_widgets.HorizontalSlider"), ("Icon choice", "forms.ChoiceField", "custom_widgets.IconChoice")] """ global NAMES, META_REQUIRED_KEYS, META_OPTIONAL_KEYS, CHOICES_REQUIRED_KEYS, CHOICES_OPTIONAL_KEYS for prop in fields_properties: field_id = prop['field_id'] try: if field_id in CLASSES: # This should never happen err = "ID %s for field %s in FORMS_EXTRA_FIELDS already exists" raise ImproperlyConfigured(err % (field_id, prop['name'])) if prop['type']: CLASSES[field_id] = import_attr(prop['type']) else: CLASSES[field_id] = None NAMES += ((field_id, _(prop['name'])), ) META_REQUIRED_KEYS[field_id] = prop.get('meta_required_keys', []) + meta_required_keys META_OPTIONAL_KEYS[field_id] = prop.get('meta_optional_keys', []) + meta_optional_keys CHOICES_REQUIRED_KEYS[field_id] = prop.get( 'choices_required_keys', []) + choices_required_keys + ['text'] CHOICES_OPTIONAL_KEYS[field_id] = prop.get( 'choices_optional_keys', []) + choices_optional_keys if strategy == "backend": WIDGETS[field_id] = import_attr(prop['widget']) elif strategy == "frontend": WIDGETS[field_id] = prop['widget'] else: raise ImproperlyConfigured( "The 'strategy' field in the forms_builder fields configuration " "must be either 'backend' or 'frontend'") except KeyError, e: raise ImproperlyConfigured( "Each custom field definition must have a '%s' key" % e.message)
# Some helper groupings of field types. CHOICES = (CHECKBOX, SELECT, RADIO_MULTIPLE) DATES = (DATE, DATE_TIME, DOB) MULTIPLE = (CHECKBOX_MULTIPLE, SELECT_MULTIPLE) # HTML5 Widgets if USE_HTML5: WIDGETS.update({ DATE: html5_field("date", forms.DateInput), DATE_TIME: html5_field("datetime", forms.DateTimeInput), DOB: html5_field("date", forms.DateInput), EMAIL: html5_field("email", forms.TextInput), NUMBER: html5_field("number", forms.TextInput), URL: html5_field("url", forms.TextInput), }) # Add any custom fields defined. for field_id, field_path, field_name in EXTRA_FIELDS: if field_id in CLASSES: err = "ID %s for field %s in FORMS_EXTRA_FIELDS already exists" raise ImproperlyConfigured(err % (field_id, field_name)) CLASSES[field_id] = import_attr(field_path) NAMES += ((field_id, _(field_name)), ) # Add/update custom widgets. for field_id, widget_path in EXTRA_WIDGETS: if field_id not in CLASSES: err = "ID %s in FORMS_EXTRA_WIDGETS does not match a field" raise ImproperlyConfigured(err % field_id) WIDGETS[field_id] = import_attr(widget_path)
# Some helper groupings of field types. CHOICES = (CHECKBOX, SELECT, RADIO_MULTIPLE) DATES = (DATE, DATE_TIME, DOB) MULTIPLE = (CHECKBOX_MULTIPLE, SELECT_MULTIPLE) # HTML5 Widgets if USE_HTML5: WIDGETS.update({ DATE: html5_field("date", forms.DateInput), DATE_TIME: html5_field("datetime", forms.DateTimeInput), DOB: html5_field("date", forms.DateInput), EMAIL: html5_field("email", forms.TextInput), NUMBER: html5_field("number", forms.TextInput), URL: html5_field("url", forms.TextInput), }) # Add any custom fields defined. for field_id, field_path, field_name in EXTRA_FIELDS: if field_id in CLASSES: err = "ID %s for field %s in FORMS_EXTRA_FIELDS already exists" raise ImproperlyConfigured(err % (field_id, field_name)) CLASSES[field_id] = import_attr(field_path) NAMES += ((field_id, _(field_name)),) # Add/update custom widgets. for field_id, widget_path in EXTRA_WIDGETS: if field_id not in CLASSES: err = "ID %s in FORMS_EXTRA_WIDGETS does not match a field" raise ImproperlyConfigured(err % field_id) WIDGETS[field_id] = import_attr(widget_path)