@staticmethod<EOL><INDENT>def get_field(param, initial=None):<DEDENT>
form_field = param.form_field<EOL>widget_data_dict = {}<EOL>appender_data_dict = {}<EOL>widget_init = {}<EOL>WOOEY_CHOICE_LIMIT = '<STR_LIT>'<EOL>choices = json.loads(param.choices)<EOL>field_kwargs = {<EOL>'<STR_LIT:label>': param.script_param.replace('<STR_LIT:_>', '<STR_LIT:U+0020>').title(),<EOL>'<STR_LIT>': param.required,<EOL>'<STR_LIT>': param.param_help,<EOL>}<EOL>multiple_choices = param.multiple_choice<EOL>choice_limit = param.max_choices<EOL>if initial is None and param.default is not None:<EOL><INDENT>initial = param.default<EOL><DEDENT>if choices:<EOL><INDENT>form_field = '<STR_LIT>' if multiple_choices else '<STR_LIT>'<EOL>base_choices = [(None, '<STR_LIT>')] if not param.required and not multiple_choices else []<EOL>field_kwargs['<STR_LIT>'] = base_choices+[(str(i), str(i).title()) for i in choices]<EOL><DEDENT>custom_widget = param.custom_widget<EOL>if custom_widget:<EOL><INDENT>if custom_widget.widget_class:<EOL><INDENT>widget_class = import_string(custom_widget.widget_class)<EOL>field_kwargs['<STR_LIT>'] = widget_class<EOL><DEDENT>widget_init['<STR_LIT>'] = custom_widget.widget_attributes<EOL><DEDENT>if form_field == '<STR_LIT>':<EOL><INDENT>if param.is_output:<EOL><INDENT>form_field = '<STR_LIT>'<EOL>if initial:<EOL><INDENT>if not isinstance(initial, (list, tuple)):<EOL><INDENT>initial = [initial]<EOL><DEDENT>initial = [os.path.split(i.name)[<NUM_LIT:1>] for i in initial]<EOL><DEDENT><DEDENT>elif initial is not None and list(filter(None, initial)):  <EOL><INDENT>if isinstance(initial, (list, tuple)):<EOL><INDENT>_initial = []<EOL>for value in initial:<EOL><INDENT>if not hasattr(value, '<STR_LIT:path>'):<EOL><INDENT>with utils.get_storage_object(value, close=False) as so:<EOL><INDENT>_initial.append(so)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>_initial.append(value)<EOL><DEDENT><DEDENT>initial = _initial<EOL><DEDENT>else:<EOL><INDENT>if not hasattr(initial, '<STR_LIT:path>'):<EOL><INDENT>with utils.get_storage_object(initial, close=False) as so:<EOL><INDENT>initial = so<EOL><DEDENT><DEDENT>else:<EOL><INDENT>initial = initial<EOL><DEDENT><DEDENT>if not field_kwargs.get('<STR_LIT>'):<EOL><INDENT>field_kwargs['<STR_LIT>'] = forms.ClearableFileInput<EOL><DEDENT><DEDENT><DEDENT>if not multiple_choices and isinstance(initial, list):<EOL><INDENT>initial = initial[<NUM_LIT:0>]<EOL><DEDENT>field_kwargs['<STR_LIT>'] = initial<EOL>field = getattr(forms, form_field)<EOL>if '<STR_LIT>' in field_kwargs:<EOL><INDENT>field_kwargs['<STR_LIT>'] = field_kwargs['<STR_LIT>'](**widget_init)<EOL><DEDENT>field = field(**field_kwargs)<EOL>if form_field != '<STR_LIT>' and multiple_choices:<EOL><INDENT>field.widget.render = mutli_render(field.widget.render, appender_data_dict=appender_data_dict)<EOL>field.widget.value_from_datadict = multi_value_from_datadict(field.widget.value_from_datadict)<EOL>field.clean = multi_value_clean(field.clean)<EOL>if choice_limit > <NUM_LIT:0>:<EOL><INDENT>appender_data_dict[WOOEY_CHOICE_LIMIT] = choice_limit<EOL><DEDENT><DEDENT>elif multiple_choices and choice_limit><NUM_LIT:0>:<EOL><INDENT>widget_data_dict[WOOEY_CHOICE_LIMIT] = choice_limit<EOL><DEDENT>field.widget.attrs.update(widget_data_dict)<EOL>return field<EOL>
Any extra field attributes for the widget for customization of Wooey at the field level
 can be added to the widget dictionary, widget_data_dict, or to the appender_data_dict, which
 is the little plus button. This is useful since there is only a single copy of the plus,
 whereas we can have multiple widgets. Thus, javascript attributes we want to add per parameter
 can be added to appender_data_dict, and attributes we want to add to the widget input itself
 can be added to the widget_data_dict.

:return: a field class