123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297 |
- from UserDict import IterableUserDict
- from django.utils import formats
- class FormLayout(object):
- def __init__(self, form, fieldsets=False):
- scaffold_fields = FormFields(form)
- scaffold_fieldsets = FormFieldsets(form, scaffold_fields.fields, fieldsets)
-
- self.multipart_form = scaffold_fields.multipart_form
- self.fieldsets = scaffold_fieldsets.fieldsets
- self.fields = scaffold_fields.fields
- self.hidden = scaffold_fields.hidden
-
- class FormFields(object):
- """
- Hydrator that builds fields list from form and blueprint
- """
- def __init__(self, form):
- self.multipart_form = False
- self.fields = {}
- self.hidden = []
-
- # Extract widgets from meta
- self.meta_widgets = {}
- try:
- self.meta_widgets = form.Meta.widgets
- except AttributeError:
- pass
-
- # Find out field input types
- for field in form.fields.keys():
- widget = self._get_widget(field, form.fields[field])
- widget_name = widget.__class__.__name__
- bound_field = form[field]
- blueprint = {
- 'attrs': {
- 'id': bound_field.auto_id,
- 'name': bound_field.html_name,
- },
- 'endrow': False,
- 'errors': [],
- 'has_value': bound_field.value() != None,
- 'help_text': bound_field.help_text,
- 'hidden': widget.is_hidden,
- 'html_id': bound_field.auto_id,
- 'html_name': bound_field.html_name,
- 'id': field,
- 'initial': bound_field.field.initial,
- 'label': bound_field.label,
- 'last': False,
- 'nested': [],
- 'required': bound_field.field.widget.is_required,
- 'show_hidden_initial': bound_field.field.show_hidden_initial,
- 'value': bound_field.value(),
- 'width': 100,
- 'widget': '',
- 'choices': [],
- }
-
- # Set multipart form
- if widget.needs_multipart_form:
- self.multipart_form = True
-
- # Get errors
- for error in bound_field._errors():
- blueprint['errors'].append(error)
- try:
- for error in form.errors[field]:
- if not error in blueprint['errors']:
- blueprint['errors'].append(error)
- except KeyError:
- pass
-
- # Use clean value instead?
- try:
- if field in form.cleaned_data:
- blueprint['value'] = form.cleaned_data[field]
- except AttributeError:
- pass
-
- # TextInput
- if widget_name in ['TextInput', 'PasswordInput', 'Textarea']:
- blueprint['widget'] = 'text'
- blueprint['attrs']['type'] = 'text'
- try:
- blueprint['attrs']['maxlength'] = bound_field.field.max_length
- except AttributeError:
- pass
-
- # PasswordInput
- if widget_name == 'PasswordInput':
- blueprint['attrs']['type'] = 'password'
-
- # Textarea
- if widget_name == 'Textarea':
- blueprint['widget'] = 'textarea'
-
- # ReCaptcha
- if widget_name == 'ReCaptchaWidget':
- blueprint['widget'] = 'recaptcha'
- blueprint['attrs'] = get_captcha_dict(
- form.request.settings,
- bound_field.field.api_error
- )
-
- # HiddenInput
- if widget_name == 'HiddenInput':
- blueprint['widget'] = 'hidden'
-
- # MultipleHiddenInput
- if widget_name == 'MultipleHiddenInput':
- blueprint['widget'] = 'multiple_hidden'
- blueprint['attrs'] = {
- 'choices': widget.choices
- }
-
- # FileInput
- if widget_name == 'FileInput':
- blueprint['widget'] = 'file'
-
- # ClearableFileInput
- if widget_name == 'ClearableFileInput':
- blueprint['widget'] = 'file_clearable'
-
- # DateInput
- if widget_name == 'DateInput':
- blueprint['widget'] = 'date'
- try:
- blueprint['value'] = blueprint['value'].strftime('%Y-%m-%d')
- except AttributeError as e:
- pass
-
- # DateTimeInput
- if widget_name == 'DateTimeInput':
- blueprint['widget'] = 'datetime'
- try:
- blueprint['value'] = blueprint['value'].strftime('%Y-%m-%d %H:%M')
- except AttributeError as e:
- pass
-
- # TimeInput
- if widget_name == 'TimeInput':
- blueprint['widget'] = 'time'
- try:
- blueprint['value'] = blueprint['value'].strftime('%H:%M')
- except AttributeError as e:
- pass
-
- # CheckboxInput
- if widget_name == 'CheckboxInput':
- blueprint['widget'] = 'checkbox'
-
- # Select, NullBooleanSelect, SelectMultiple, RadioSelect, CheckboxSelectMultiple
- if widget_name in ['Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect', 'CheckboxSelectMultiple']:
- blueprint['choices'] = widget.choices
-
- # Yes-no radio select
- if widget_name == 'YesNoSwitch':
- blueprint['widget'] = 'yes_no_switch'
-
- # Select
- if widget_name == 'Select':
- blueprint['widget'] = 'select'
- if not blueprint['value']:
- blueprint['value'] = u''
-
- # NullBooleanSelect
- if widget_name == 'NullBooleanSelect':
- blueprint['widget'] = 'null_boolean_select'
-
- # SelectMultiple
- if widget_name == 'SelectMultiple':
- blueprint['widget'] = 'select_multiple'
-
- # RadioSelect
- if widget_name == 'RadioSelect':
- blueprint['widget'] = 'radio_select'
- if not blueprint['value']:
- blueprint['value'] = u''
-
- # CheckboxSelectMultiple
- if widget_name == 'CheckboxSelectMultiple':
- blueprint['widget'] = 'checkbox_select_multiple'
-
- # MultiWidget
- if widget_name == 'MultiWidget':
- blueprint['widget'] = 'multi'
-
- # SplitDateTimeWidget
- if widget_name == 'SplitDateTimeWidget':
- blueprint['widget'] = 'split_datetime'
-
- # SplitHiddenDateTimeWidget
- if widget_name == 'SplitHiddenDateTimeWidget':
- blueprint['widget'] = 'split_hidden_datetime'
-
- # SelectDateWidget
- if widget_name == 'SelectDateWidget':
- blueprint['widget'] = 'select_date'
- blueprint['years'] = widget.years
-
- # Store field in either of collections
- if blueprint['hidden']:
- blueprint['attrs']['type'] = 'hidden'
- self.hidden.append(blueprint)
- else:
- self.fields[field] = blueprint
-
- def _get_widget(self, name, field):
- if name in self.meta_widgets:
- return self.meta_widgets[name]
- return field.widget
-
-
- class FormFieldsets(object):
- """
- Hydrator that builds fieldset from form and blueprint
- """
- def __init__(self, form, fields, fieldsets=None):
- self.fieldsets = []
-
- # Use form layout
- if not fieldsets:
- try:
- fieldsets = form.layout
- except AttributeError:
- pass
-
- # Build fieldsets data
- if fieldsets:
- for blueprint in fieldsets:
- fieldset = {'legend': None, 'fields': [], 'help': None, 'last': False}
- fieldset['legend'] = blueprint[0]
- row_width = 0
- for field in blueprint[1]:
- try:
- if isinstance(field, basestring):
- fieldset['fields'].append(fields[field])
- elif field[0] == 'nested':
- subfields = {'label': None, 'help_text': None, 'nested': [], 'errors':[], 'endrow': False, 'last': False, 'width': 100}
- subfiels_ids = []
- try:
- subfields = field[2].update(subfields)
- except IndexError:
- pass
- for subfield in field[1]:
- if isinstance(subfield, basestring):
- subfiels_ids.append(subfield)
- subfields['nested'].append(fields[subfield])
- for error in fields[subfield]['errors']:
- if not error in subfields['errors']:
- subfields['errors'].append(error)
- else:
- subfiels_ids.append(subfield[0])
- try:
- subfield[1]['attrs'] = dict(fields[subfield[0]]['attrs'], **subfield[1]['attrs'])
- except KeyError:
- pass
- subfields['nested'].append(dict(fields[subfield[0]], **subfield[1]))
- for error in fields[subfield[0]]['errors']:
- if not error in subfields['errors']:
- subfields['errors'].append(error)
- if not subfields['label']:
- subfields['label'] = subfields['nested'][0]['label']
- if not subfields['help_text']:
- subfields['help_text'] = subfields['nested'][0]['help_text']
- try:
- subfields['errors'] = form.errors["_".join(subfiels_ids)]
- except KeyError:
- pass
- fieldset['fields'].append(subfields)
- else:
- try:
- field[1]['attrs'] = dict(fields[field[0]]['attrs'], **field[1]['attrs'])
- except KeyError:
- pass
- fieldset['fields'].append(dict(fields[field[0]], **field[1]))
- row_width += fieldset['fields'][-1]['width']
- if row_width >= 100:
- fieldset['fields'][-1]['endrow'] = True
- row_width = 0
- except (AttributeError, IndexError, KeyError):
- pass
- if fieldset['fields']:
- fieldset['fields'][-1]['endrow'] = True
- fieldset['fields'][-1]['last'] = True
- try:
- fieldset['help'] = blueprint[2]
- except IndexError:
- pass
-
- # Append complete fieldset
- if fieldset['fields']:
- self.fieldsets.append(fieldset)
- self.fieldsets[-1]['last'] = True
-
-
|