diff --git a/.gitignore b/.gitignore index 2803757..0dd5b16 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.*~ *.egg-info *.pyc +.vscode/settings.json diff --git a/django_remote_forms/fields.py b/django_remote_forms/fields.py index 4e0d33a..400bd40 100644 --- a/django_remote_forms/fields.py +++ b/django_remote_forms/fields.py @@ -5,6 +5,7 @@ from django.conf import settings from django_remote_forms import logger, widgets +from django import forms class RemoteField(object): @@ -40,7 +41,7 @@ def as_dict(self): try: remote_widget_class = getattr(widgets, remote_widget_class_name) remote_widget = remote_widget_class(self.field.widget, field_name=self.field_name) - except Exception, e: + except Exception as e: logger.warning('Error serializing %s: %s', remote_widget_class_name, str(e)) widget_dict = {} else: @@ -208,6 +209,10 @@ def as_dict(self): return super(RemoteMultipleChoiceField, self).as_dict() +class RemoteCommaSeparatedField(RemoteMultipleChoiceField): + pass + + class RemoteModelMultipleChoiceField(RemoteMultipleChoiceField): def as_dict(self): return super(RemoteModelMultipleChoiceField, self).as_dict() @@ -276,3 +281,16 @@ def as_dict(self): class RemoteSlugField(RemoteCharField): def as_dict(self): return super(RemoteSlugField, self).as_dict() + + +class CommaSeparatedField(forms.MultipleChoiceField): + + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + + def prepare_value(self, value): + return value.split(',') if value else value + + def clean(self, value): + value = super().clean(value) + return ','.join(value) diff --git a/django_remote_forms/forms.py b/django_remote_forms/forms.py index 26b38fb..b21793f 100644 --- a/django_remote_forms/forms.py +++ b/django_remote_forms/forms.py @@ -3,6 +3,7 @@ from django_remote_forms import fields, logger from django_remote_forms.utils import resolve_promise +from django.forms import ModelMultipleChoiceField class RemoteForm(object): def __init__(self, form, *args, **kwargs): @@ -121,12 +122,19 @@ def as_dict(self): form_dict['ordered_fields'] = self.fields initial_data = {} + foreign_key_fields = [] + comma_separated_fields = [] for name, field in [(x, self.form.fields[x]) for x in self.fields]: # Retrieve the initial data from the form itself if it exists so # that we properly handle which initial data should be returned in # the dictionary. + if type(field) in [ModelMultipleChoiceField]: + foreign_key_fields.append(name) + elif type(field) in [fields.CommaSeparatedField]: + comma_separated_fields.append(name) + # Please refer to the Django Form API documentation for details on # why this is necessary: # https://docs.djangoproject.com/en/dev/ref/forms/api/#dynamic-initial-values @@ -138,7 +146,7 @@ def as_dict(self): try: remote_field_class = getattr(fields, remote_field_class_name) remote_field = remote_field_class(field, form_initial_field_data, field_name=name) - except Exception, e: + except Exception as e: logger.warning('Error serializing field %s: %s', remote_field_class_name, str(e)) field_dict = {} else: @@ -155,9 +163,26 @@ def as_dict(self): initial_data[name] = form_dict['fields'][name]['initial'] + form_data = self.form.data.copy() + + # Filter data to include only form fields data + form_data = {k: v for k, v in self.form.data.items() if k in list(self.fields)} + if self.form.data: - form_dict['data'] = self.form.data + form_dict['data'] = form_data else: form_dict['data'] = initial_data + for field_name in foreign_key_fields: + obj_list = form_dict['data'].get(field_name, []) + if obj_list: + form_dict['data'][field_name] = [obj.pk for obj in obj_list] + + for field_name in comma_separated_fields: + obj = form_dict['data'].get(field_name, '') + if obj: + form_dict['data'][field_name] = obj.split(',') + else: + form_dict['data'][field_name] = [] + return resolve_promise(form_dict) diff --git a/django_remote_forms/utils.py b/django_remote_forms/utils.py index 0391fa0..cc47c2a 100644 --- a/django_remote_forms/utils.py +++ b/django_remote_forms/utils.py @@ -1,5 +1,5 @@ from django.utils.functional import Promise -from django.utils.encoding import force_unicode +from django.utils.encoding import force_text def resolve_promise(o): @@ -10,7 +10,7 @@ def resolve_promise(o): o = [resolve_promise(x) for x in o] elif isinstance(o, Promise): try: - o = force_unicode(o) + o = force_text(o) except: # Item could be a lazy tuple or list try: diff --git a/django_remote_forms/widgets.py b/django_remote_forms/widgets.py index d66a3fb..ac0c7af 100644 --- a/django_remote_forms/widgets.py +++ b/django_remote_forms/widgets.py @@ -193,6 +193,10 @@ def as_dict(self): return widget_dict +class RemoteFilteredSelectMultiple(RemoteSelectMultiple): + pass + + class RemoteRadioInput(RemoteWidget): def as_dict(self): widget_dict = OrderedDict()