Skip to content
47 changes: 41 additions & 6 deletions django_remote_forms/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from django_remote_forms import logger, widgets

from django.utils.translation import gettext as _

class RemoteField(object):
"""
Expand All @@ -28,7 +29,7 @@ def as_dict(self):
field_dict = OrderedDict()
field_dict['title'] = self.field.__class__.__name__
field_dict['required'] = self.field.required
field_dict['label'] = self.field.label
field_dict['label'] = _(' '.join(list(map(lambda x: x.capitalize(), self.field.label.split(' ')))))
field_dict['initial'] = self.form_initial_data or self.field.initial
field_dict['help_text'] = self.field.help_text

Expand All @@ -37,17 +38,23 @@ def as_dict(self):
# Instantiate the Remote Forms equivalent of the widget if possible
# in order to retrieve the widget contents as a dictionary.
remote_widget_class_name = 'Remote%s' % self.field.widget.__class__.__name__
if hasattr(self.field.widget, 'parent_class'):
remote_widget_class_name = 'Remote%s' % self.field.widget.parent_class

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:
widget_dict = remote_widget.as_dict()

field_dict['widget'] = widget_dict

if hasattr(self.field.widget, 'input_type'):
field_dict['widget']['input_type'] = self.field.widget.input_type

return field_dict


Expand Down Expand Up @@ -104,7 +111,7 @@ def as_dict(self):

# If initial value is datetime then convert it using first available input format
if (isinstance(field_dict['initial'], (datetime.datetime, datetime.time, datetime.date))):
if not len(field_dict['input_formats']):
if not getattr(field_dict['input_formats'], 'len', None):
if isinstance(field_dict['initial'], datetime.date):
field_dict['input_formats'] = settings.DATE_INPUT_FORMATS
elif isinstance(field_dict['initial'], datetime.time):
Expand All @@ -125,6 +132,7 @@ def as_dict(self):

class RemoteDateTimeField(RemoteTimeField):
def as_dict(self):
print('RemoteDateTimeField')
return super(RemoteDateTimeField, self).as_dict()


Expand Down Expand Up @@ -175,7 +183,6 @@ def as_dict(self):
class RemoteChoiceField(RemoteField):
def as_dict(self):
field_dict = super(RemoteChoiceField, self).as_dict()

field_dict['choices'] = []
for key, value in self.field.choices:
field_dict['choices'].append({
Expand All @@ -188,7 +195,21 @@ def as_dict(self):

class RemoteModelChoiceField(RemoteChoiceField):
def as_dict(self):
return super(RemoteModelChoiceField, self).as_dict()
form_as_dict = super(RemoteModelChoiceField, self).as_dict()

field = self.__dict__.get('field', {})
if hasattr(field, '_queryset'):
queryset = self.__dict__['field'].__dict__['_queryset']
model = queryset.model()
app_name = model.app_name if hasattr(model, 'app_name') else None
model_name = model.model_name if hasattr(model, 'model_name') else None

form_as_dict.update({
'app_name' : app_name,
'model_name' : model_name,
})

return form_as_dict


class RemoteTypedChoiceField(RemoteChoiceField):
Expand All @@ -210,7 +231,21 @@ def as_dict(self):

class RemoteModelMultipleChoiceField(RemoteMultipleChoiceField):
def as_dict(self):
return super(RemoteModelMultipleChoiceField, self).as_dict()
form_as_dict = super(RemoteModelMultipleChoiceField, self).as_dict()

field = self.__dict__.get('field', {})
if hasattr(field, '_queryset'):
queryset = self.__dict__['field'].__dict__['_queryset']
model = queryset.model()
app_name = model.app_name if hasattr(model, 'app_name') else None
model_name = model.model_name if hasattr(model, 'model_name') else None

form_as_dict.update({
'app_name' : app_name,
'model_name' : model_name,
})

return form_as_dict


class RemoteTypedMultipleChoiceField(RemoteMultipleChoiceField):
Expand Down
15 changes: 10 additions & 5 deletions django_remote_forms/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ def __init__(self, form, *args, **kwargs):

self.all_fields = set(self.form.fields.keys())

self.title = kwargs.pop('title', None)
self.excluded_fields = set(kwargs.pop('exclude', []))
self.included_fields = set(kwargs.pop('include', []))
self.readonly_fields = set(kwargs.pop('readonly', []))
Expand Down Expand Up @@ -108,7 +109,8 @@ def as_dict(self):
}
"""
form_dict = OrderedDict()
form_dict['title'] = self.form.__class__.__name__

form_dict['title'] = self.title if self.title else self.form.__class__.__name__
form_dict['non_field_errors'] = self.form.non_field_errors()
form_dict['label_suffix'] = self.form.label_suffix
form_dict['is_bound'] = self.form.is_bound
Expand All @@ -122,7 +124,7 @@ def as_dict(self):

initial_data = {}

for name, field in [(x, self.form.fields[x]) for x in self.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.
Expand All @@ -138,7 +140,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:
Expand All @@ -153,11 +155,14 @@ def as_dict(self):
if 'initial' not in form_dict['fields'][name]:
form_dict['fields'][name]['initial'] = None

initial_data[name] = form_dict['fields'][name]['initial']
# Remove the coerce key from the field, it will not be used
if form_dict['fields'][name].get('coerce'):
form_dict['fields'][name].pop('coerce')

initial_data[name] = form_dict['fields'][name]['initial']
if self.form.data:
form_dict['data'] = self.form.data
else:
form_dict['data'] = initial_data

return resolve_promise(form_dict)
15 changes: 11 additions & 4 deletions django_remote_forms/utils.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,19 @@
from django.utils.functional import Promise
from django.utils.encoding import force_unicode

from django.utils.encoding import force_text
from django.forms.models import ModelChoiceIteratorValue
from django.db import models

def resolve_promise(o):
if isinstance(o, dict):
for k, v in o.items():
o[k] = resolve_promise(v)
if isinstance(o[k], ModelChoiceIteratorValue):
o[k] = getattr(o[k], 'value')
elif isinstance(o, (list, tuple)):
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:
Expand All @@ -19,5 +22,9 @@ def resolve_promise(o):
raise Exception('Unable to resolve lazy object %s' % o)
elif callable(o):
o = o()

elif isinstance(o, models.Model): # New treatment for models instances, return the model instance id
try:
o = o.id
except Exception as e:
print(e)
return o