Skip to content

Django remote forms syntax correction #34

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

Open
wants to merge 26 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f802e30
Fixed datetime initial value verification
gabriel-taufer Sep 23, 2020
1ce0a49
Fix exception error syntax
gabriel-taufer Sep 23, 2020
d31fd85
Change force_unicode to force_text import from django.utils.encoding
gabriel-taufer Sep 23, 2020
579f6ec
Merge branch 'master' of https://github.com/GabrielTaufer/django-remo…
gabriel-taufer Sep 23, 2020
bf56787
Form as dict hotfix
gabriel-taufer Oct 12, 2020
c6f0cab
Add model and APP name to RemoteModelChoiceField
gabriel-taufer Oct 12, 2020
9470a8c
Fix form FKs translation
gabriel-taufer Nov 5, 2020
1215430
Add new model instance treatment on resolve_promise function
gabriel-taufer Nov 6, 2020
c18c289
Implement field subclass possibility
lucas-soranzo Dec 16, 2020
2889d74
Merge branch 'master' of https://github.com/gabriel-taufer/django-rem…
lucas-soranzo Dec 16, 2020
4be2287
Merge pull request #1 from gabriel-taufer/feat/subclass
lucas-soranzo Dec 18, 2020
0f11257
Add aditional props to the default widget
lucas-soranzo Dec 21, 2020
24a992b
Update fileinput initial value
lucas-soranzo Feb 7, 2021
f2d8510
Adjust initial on filefield
lucas-soranzo Feb 7, 2021
51fb405
fix(datetime-input): fix datetime input field format logic
gabriel-taufer Jun 5, 2021
170a309
Widget choices crash hotfix
lucas-soranzo Aug 19, 2021
b8ff012
Fix for tuples on widget choices
lucas-soranzo Sep 5, 2021
8401260
Hotfix for initial value on float field
lucas-soranzo Mar 12, 2023
b5748ba
Hotfix for initial value on float field
lucas-soranzo Mar 12, 2023
4dd632d
Hotfix for initial value on float field
lucas-soranzo Mar 12, 2023
df88dff
fix: adjust remote form field validation for input_format logic so it…
gabriel-taufer May 6, 2024
0fbcdb0
Merge pull request #2 from gabriel-taufer/fix/input_formats-validator
gabriel-taufer May 6, 2024
cf40abb
fix: adjust remote form field validation for input_format logic so it…
gabriel-taufer May 7, 2024
a4d514e
Merge pull request #3 from gabriel-taufer/fix/input_formats-validator
gabriel-taufer May 7, 2024
3ee3c05
fix: remove line that was mispasted
gabriel-taufer May 7, 2024
f01097c
Merge pull request #4 from gabriel-taufer/fix/input_formats-validator
gabriel-taufer May 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
84 changes: 64 additions & 20 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 @@ -24,30 +25,40 @@ def __init__(self, field, form_initial_data=None, field_name=None):
self.field = field
self.form_initial_data = form_initial_data

@property
def initial(self):
return self.form_initial_data or self.field.initial

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['initial'] = self.form_initial_data or self.field.initial
field_dict['label'] = _(self.field.label)
field_dict['initial'] = self.initial
field_dict['help_text'] = self.field.help_text

field_dict['error_messages'] = self.field.error_messages

# 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 @@ -76,6 +87,12 @@ def as_dict(self):


class RemoteFloatField(RemoteIntegerField):
@property
def initial(self):
if type(self.form_initial_data) == float:
return self.form_initial_data
return self.field.initial

def as_dict(self):
return super(RemoteFloatField, self).as_dict()

Expand Down Expand Up @@ -103,14 +120,22 @@ def as_dict(self):
field_dict['initial'] = field_dict['initial']()

# 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 isinstance(field_dict['initial'], datetime.date):
# Hotfix to check input formats
input_formats = field_dict.get('input_formats', [])
try:
has_input_formats = input_formats[0] is not None
except Exception as _:
has_input_formats = False

if not has_input_formats:
if isinstance(field_dict['initial'], datetime.datetime):
field_dict['input_formats'] = settings.DATETIME_INPUT_FORMATS
elif isinstance(field_dict['initial'], datetime.date):
field_dict['input_formats'] = settings.DATE_INPUT_FORMATS
elif isinstance(field_dict['initial'], datetime.time):
field_dict['input_formats'] = settings.TIME_INPUT_FORMATS
elif isinstance(field_dict['initial'], datetime.datetime):
field_dict['input_formats'] = settings.DATETIME_INPUT_FORMATS

input_format = field_dict['input_formats'][0]
field_dict['initial'] = field_dict['initial'].strftime(input_format)
Expand Down Expand Up @@ -148,6 +173,7 @@ def as_dict(self):
field_dict = super(RemoteFileField, self).as_dict()

field_dict['max_length'] = self.field.max_length
field_dict['initial'] = str(field_dict['initial']) if field_dict['initial'] is not None else None

return field_dict

Expand All @@ -173,22 +199,26 @@ 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({
'value': key,
'display': value
})

return field_dict
pass


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 +240,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
35 changes: 27 additions & 8 deletions django_remote_forms/widgets.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,32 @@ def as_dict(self):
widget_dict['is_required'] = self.widget.is_required
widget_dict['attrs'] = self.widget.attrs

if hasattr(self.widget, 'related_field'):
widget_dict['related_field'] = self.widget.related_field

if hasattr(self.widget, 'choices'):
widget_dict['choices'] = widget_dict.get('choices', [])
if type(self.widget.choices) is list:
self.widget.choices = self.widget.choices
elif type(self.widget.choices) is tuple:
self.widget.choices = list(self.widget.choices)
else:
print(self.widget.choices)
print(f"Unable to parse type {type(self.widget.choices)} for widget choices")
widget_dict['choices'] = []
self.widget.choices = []

for key, value, *data in self.widget.choices:
complementary_data = {}
if len(data) and type(data[0]) is dict:
complementary_data = data[0]

widget_dict['choices'].append(dict(
**complementary_data,
value = key,
display = value
))

return widget_dict


Expand Down Expand Up @@ -166,13 +192,6 @@ class RemoteSelect(RemoteWidget):
def as_dict(self):
widget_dict = super(RemoteSelect, self).as_dict()

widget_dict['choices'] = []
for key, value in self.widget.choices:
widget_dict['choices'].append({
'value': key,
'display': value
})

widget_dict['input_type'] = 'select'

return widget_dict
Expand All @@ -188,7 +207,7 @@ def as_dict(self):
widget_dict = super(RemoteSelectMultiple, self).as_dict()

widget_dict['input_type'] = 'selectmultiple'
widget_dict['size'] = len(widget_dict['choices'])
widget_dict['size'] = len(widget_dict.get('choices', []))

return widget_dict

Expand Down