Skip to content
This repository has been archived by the owner on Aug 18, 2019. It is now read-only.

Commit

Permalink
form.as_dict() and form.as_json()
Browse files Browse the repository at this point in the history
  • Loading branch information
jpsca committed Jan 28, 2016
1 parent ff18496 commit b7c7c8f
Show file tree
Hide file tree
Showing 12 changed files with 306 additions and 10 deletions.
2 changes: 1 addition & 1 deletion solution/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@
from .utils import Markup, get_html_attrs, to_unicode # noqa


__version__ = '5.1.1'
__version__ = '5.2.0'
8 changes: 8 additions & 0 deletions solution/fields/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import inspect
import re

from .field import Field
from .text import Text


Expand Down Expand Up @@ -58,6 +59,11 @@ def __init__(self, sep=', ', filters=None, **kwargs):
self.filters = [f() if inspect.isclass(f) else f for f in filters]
super(Collection, self).__init__(**kwargs)

def as_dict(self):
dd = Field.as_dict(self)
dd['value'] = self._split_values(self.str_value) or []
return dd

def _clean_data(self, str_value, file_data, obj_value):
if isinstance(str_value, (list, tuple)):
if len(str_value):
Expand Down Expand Up @@ -99,5 +105,7 @@ def py_to_str(self, **kwargs):
return self.sep.join(self.obj_value)

def _split_values(self, str_value):
if not str_value:
return []
values = re.split(self.rxsep, str_value.strip())
return filter(lambda x: x != u'', values)
7 changes: 7 additions & 0 deletions solution/fields/field.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,13 @@ def error_tag(self, tmpl=u'<div {attrs}>{msg}</div>', **kwargs):
)
return Markup(html)

def as_dict(self):
return {
'name': self.name,
'value': self.value or u'',
'error': self.error.message if self.error else u'',
}


def validator_in(validator, validators_list):
for val in validators_list:
Expand Down
11 changes: 11 additions & 0 deletions solution/fields/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ def __call__(self, **kwargs):
return self.as_select(_items=items, **kwargs)
return self.as_radios(_items=items, **kwargs)

def as_dict(self):
dd = Field.as_dict(self)
dd['items'] = self.items
return dd

def as_select(self, _items=None, **kwargs):
"""Render the field as a `<select>` element.
Expand Down Expand Up @@ -272,6 +277,12 @@ def __iter__(self):
for item in self.items:
yield item

def as_dict(self):
dd = Field.as_dict(self)
dd['items'] = self.items
dd['value'] = dd.get('value') or []
return dd

def _clean_data(self, str_value, file_data, obj_value):
"""This overwrite is neccesary for work with multivalues"""
str_value = str_value or None
Expand Down
24 changes: 24 additions & 0 deletions solution/form.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@
from copy import copy
import inspect

try:
import simplejson as json
except ImportError:
import json

from ._compat import itervalues
from .fields import Field
from .formset import FormSet
Expand Down Expand Up @@ -128,6 +133,25 @@ def _init_fields(self):
self._forms = forms
self._sets = sets

def as_dict(self):
dd = {
field.name: field.as_dict()
for field in self._fields.values()
}
dd.update({
name: form.as_dict()
for name, form in self._forms.items()
})
dd.update({
name: formset.as_dict()
for name, formset in self._sets.items()
})
return dd

def as_json(self):
"""Useful for inserting the form data as a JavaScript object."""
return json.dumps(self.as_dict())

def prepare(self, data):
"""You can overwrite this method to store the logic of pre-processing
the input data.
Expand Down
3 changes: 3 additions & 0 deletions solution/formset.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ def _init(self, data=None, objs=None, files=None):
if hasattr(mo, 'db'):
mo.db.session.delete(mo)

def as_dict(self):
return [form.as_dict() for form in self._forms]

def _get_fullname(self, num):
return '{name}.{num}'.format(
name=self._name or self._form_class.__name__.lower(),
Expand Down
22 changes: 21 additions & 1 deletion tests/test_collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ def lists_are_equal(l1, l2):
return all(map(eq, l1, l2))


def test_render_collection():
def test_render_():
field = f.Collection()
field.name = 'abc'
field.load_data(u'a, b,c')
Expand Down Expand Up @@ -73,3 +73,23 @@ def filter_the_b(py_value):
field.name = 'abc'
field.load_data([u'a@example.com,b@example.com'])
assert field.validate() == [u'a@example.com', u'b@example.com']


def test_collection_as_dict():
field = f.Collection()
field.name = 'abc'

expdict = {
'name': u'abc',
'value': [],
'error': '',
}
result = sorted(list(field.as_dict().items()))
expected = sorted(list(expdict.items()))
assert result == expected

field.load_data(u'a, b,c')
expdict['value'] = u'a,b,c'.split(',')
result = sorted(list(field.as_dict().items()))
expected = sorted(list(expdict.items()))
assert result == expected
16 changes: 16 additions & 0 deletions tests/test_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -390,3 +390,19 @@ def test_validate_file():
field.load_data(obj_value=u'obj value', file_data=u'file data')
assert field.validate() == u'file data'
assert not field.error


def test_field_as_dict():
message = u'Lorem ipsum'
field = f.Field(validate=[f.Required(message)])
field.name = u'abc'
assert field.validate() is None

expdict = {
'name': u'abc',
'value': u'',
'error': message,
}
result = sorted(list(field.as_dict().items()))
expected = sorted(list(expdict.items()))
assert result == expected
173 changes: 169 additions & 4 deletions tests/test_forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


class ContactForm(f.Form):
subject = f.Text(validate=[f.Required])
subject = f.Text(validate=[f.Required(u'required')])
email = f.Text(validate=[f.ValidEmail])
message = f.Text(validate=[
f.Required(message=u'write something!')
Expand Down Expand Up @@ -54,9 +54,15 @@ def test_obj_data():
}
form = ContactForm(data, obj=obj)
expected = {
'subject': '<input name="subject" type="text" value="%s" required>' % data['subject'],
'email': '<input name="email" type="text" value="%s">' % obj['email'],
'message': '<input name="message" type="text" value="%s" required>' % data['message'],
'subject': '<input name="subject" type="text" value="{}" required>'.format(
data['subject']
),
'email': '<input name="email" type="text" value="{}">'.format(
obj['email']
),
'message': '<input name="message" type="text" value="{}" required>'.format(
data['message']
),
}
for field in form:
assert expected[field.name] == field()
Expand Down Expand Up @@ -511,3 +517,162 @@ class ProfileForm(f.Form):
form = ProfileForm(data, profile)
obj = form.save()
assert obj['photo'] == None


def test_simple_form_as_dict():
data = {
'subject': u'Hello',
}
obj = {
'email': u'info@lucumalabs.com',
}
form = ContactForm(data, obj=obj)

expdict = {
u'subject': {
'name': u'subject',
'value': data[u'subject'],
'error': u'',
},
u'email': {
'name': u'email',
'value': obj['email'],
'error': u'',
},
u'message': {
'name': u'message',
'value': u'',
'error': u'',
},
}
result = sorted(list(form.as_dict().items()))
expected = sorted(list(expdict.items()))
assert result == expected

assert not form.is_valid()
expdict = {
u'subject': {
'name': u'subject',
'value': data[u'subject'],
'error': u'',
},
u'email': {
'name': u'email',
'value': obj['email'],
'error': u'',
},
u'message': {
'name': u'message',
'value': u'',
'error': u'write something!',
},
}
result = sorted(list(form.as_dict().items()))
expected = sorted(list(expdict.items()))
assert result == expected
assert form.as_json()


def test_simple_prefixed_form_as_dict():
data = {
'meh-subject': u'Hello',
}
obj = {
'email': u'info@lucumalabs.com',
}
form = ContactForm(data, obj=obj, prefix=u'meh')

expdict = {
u'meh-subject': {
'name': u'meh-subject',
'value': data[u'meh-subject'],
'error': u'',
},
u'meh-email': {
'name': u'meh-email',
'value': obj['email'],
'error': u'',
},
u'meh-message': {
'name': u'meh-message',
'value': u'',
'error': u'',
},
}
print(form.as_dict())
result = sorted(list(form.as_dict().items()))
expected = sorted(list(expdict.items()))
assert result == expected
assert form.as_json()


def test_form_with_subform_as_dict():
class FormA(f.Form):
a = f.Text()

class WrapForm(f.Form):
fa = FormA

data = {
'fa.a': u'A',
}
form = WrapForm(data)

expdict = {
'fa': {
'fa.a': {
'name': u'fa.a',
'value': u'A',
'error': u'',
}
},
}
result = sorted(list(form.as_dict().items()))
expected = sorted(list(expdict.items()))
assert result == expected
assert form.as_json()


def test_form_with_formset_as_dict():
class MyForm(f.Form):
a = f.Text(validate=[f.Required])
b = f.Text(validate=[f.Required])

class WrapForm(f.Form):
subs = f.FormSet(MyForm)

form = WrapForm({'subs.1-a': 'foo', 'subs.2-b': 'bar'})

expdict = {
'subs': [
{
'subs.1-a': {
'name': u'subs.1-a',
'value': u'foo',
'error': u'',
},
'subs.1-b': {
'name': u'subs.1-b',
'value': u'',
'error': u'',
},
},
{
'subs.2-a': {
'name': u'subs.2-a',
'value': u'',
'error': u'',
},
'subs.2-b': {
'name': u'subs.2-b',
'value': u'bar',
'error': u'',
},
},
],
}
print(form.as_dict())
result = sorted(list(form.as_dict().items()))
expected = sorted(list(expdict.items()))
assert result == expected
assert form.as_json()
4 changes: 0 additions & 4 deletions tests/test_formsets.py
Original file line number Diff line number Diff line change
Expand Up @@ -360,7 +360,3 @@ class WrapForm(f.Form):
print('# form.subs._forms[0].a.name ==', form.subs._forms[0].a.name)
assert form.subs.form.a.name == 'subs.1-a'
assert form.subs._forms[0].a.name == 'subs.1-a'


if __name__ == '__main__':
test_formset_names()
23 changes: 23 additions & 0 deletions tests/test_multiselects.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,26 @@ def test_validate_multiselect():
field.load_data([u'xxx'])
assert field.validate() is None
assert field.error


def test_multiselect_as_dict():
items = [(1, u'A'), (2, u'B'), (3, u'C'), (4, u'D'), (5, u'Curaçao'),
(6, u'F'), (7, u'G'), (8, 'Curaçao')]
field = f.MultiSelect(items=items)
field.name = u'abc'

expdict = {
'name': u'abc',
'items': items,
'value': [],
'error': '',
}
result = sorted(list(field.as_dict().items()))
expected = sorted(list(expdict.items()))
assert result == expected

field.load_data([u'2', u'3'])
expdict['value'] = [u'2', u'3']
result = sorted(list(field.as_dict().items()))
expected = sorted(list(expdict.items()))
assert result == expected
Loading

0 comments on commit b7c7c8f

Please sign in to comment.