Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/subclass #35

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
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