add possibility to create a formdef object from a json value (#5348)
This commit is contained in:
parent
4b21a5cad0
commit
afad1c2c59
|
@ -22,23 +22,42 @@ def setup_module(module):
|
|||
def teardown_module(module):
|
||||
shutil.rmtree(pub.APP_DIR)
|
||||
|
||||
def assert_import_export_works(formdef, include_id=False):
|
||||
def export_to_indented_xml(formdef, include_id=False):
|
||||
formdef_xml = formdef.export_to_xml(include_id=include_id)
|
||||
indent(formdef_xml)
|
||||
return formdef_xml
|
||||
|
||||
def assert_compare_formdef(formdef1, formdef2, include_id=False):
|
||||
assert ET.tostring(export_to_indented_xml(formdef1, include_id=include_id)) == \
|
||||
ET.tostring(export_to_indented_xml(formdef2, include_id=include_id))
|
||||
assert formdef1.export_to_json(include_id=include_id, indent=2) == \
|
||||
formdef2.export_to_json(include_id=include_id, indent=2)
|
||||
|
||||
def assert_xml_import_export_works(formdef, include_id=False):
|
||||
formdef2 = FormDef.import_from_xml_tree(
|
||||
formdef.export_to_xml(include_id=include_id), include_id=include_id)
|
||||
assert ET.tostring(indent(formdef.export_to_xml(include_id=include_id))
|
||||
) == ET.tostring(indent(formdef2.export_to_xml(include_id=include_id)))
|
||||
assert_compare_formdef(formdef, formdef2, include_id=include_id)
|
||||
return formdef2
|
||||
|
||||
def assert_json_import_export_works(formdef, include_id=False):
|
||||
formdef2 = FormDef.import_from_json(
|
||||
StringIO.StringIO(formdef.export_to_json(include_id=include_id)), include_id=include_id)
|
||||
assert_compare_formdef(formdef, formdef2, include_id=include_id)
|
||||
return formdef2
|
||||
|
||||
def test_empty():
|
||||
formdef = FormDef()
|
||||
formdef.name = 'empty'
|
||||
assert_import_export_works(formdef)
|
||||
assert_xml_import_export_works(formdef)
|
||||
assert_json_import_export_works(formdef)
|
||||
|
||||
def test_text_attributes():
|
||||
formdef = FormDef()
|
||||
formdef.name = 'Foo'
|
||||
formdef.url_name = 'foo'
|
||||
f2 = assert_import_export_works(formdef)
|
||||
f2 = assert_xml_import_export_works(formdef)
|
||||
assert f2.url_name == formdef.url_name
|
||||
f2 = assert_json_import_export_works(formdef)
|
||||
assert f2.url_name == formdef.url_name
|
||||
|
||||
def test_boolean_attributes():
|
||||
|
@ -47,7 +66,10 @@ def test_boolean_attributes():
|
|||
formdef.url_name = 'foo'
|
||||
formdef.confirmation = True
|
||||
formdef.allow_drafts = True
|
||||
f2 = assert_import_export_works(formdef)
|
||||
f2 = assert_xml_import_export_works(formdef)
|
||||
assert f2.allow_drafts == formdef.allow_drafts
|
||||
assert f2.confirmation == formdef.confirmation
|
||||
f2 = assert_json_import_export_works(formdef)
|
||||
assert f2.allow_drafts == formdef.allow_drafts
|
||||
assert f2.confirmation == formdef.confirmation
|
||||
|
||||
|
@ -55,9 +77,11 @@ def test_a_field():
|
|||
formdef = FormDef()
|
||||
formdef.name = 'Foo'
|
||||
formdef.fields = [
|
||||
fields.StringField(type='string', id=1, label='Bar', size=40)
|
||||
fields.StringField(type='string', id=1, label='Bar', size='40')
|
||||
]
|
||||
f2 = assert_import_export_works(formdef)
|
||||
f2 = assert_xml_import_export_works(formdef)
|
||||
assert len(f2.fields) == len(formdef.fields)
|
||||
f2 = assert_json_import_export_works(formdef)
|
||||
assert len(f2.fields) == len(formdef.fields)
|
||||
|
||||
def test_more_fields():
|
||||
|
@ -70,7 +94,13 @@ def test_more_fields():
|
|||
fields.DateField(type='date', label='Bar', minimum_date='2014-01-01'),
|
||||
fields.ItemField(type='item', label='Bar', items=['foo', 'bar', 'baz']),
|
||||
]
|
||||
f2 = assert_import_export_works(formdef)
|
||||
f2 = assert_xml_import_export_works(formdef)
|
||||
assert len(f2.fields) == len(formdef.fields)
|
||||
assert f2.fields[2].type == formdef.fields[2].type
|
||||
assert f2.fields[3].minimum_date == formdef.fields[3].minimum_date
|
||||
assert f2.fields[4].items == formdef.fields[4].items
|
||||
|
||||
f2 = assert_json_import_export_works(formdef)
|
||||
assert len(f2.fields) == len(formdef.fields)
|
||||
assert f2.fields[2].type == formdef.fields[2].type
|
||||
assert f2.fields[3].minimum_date == formdef.fields[3].minimum_date
|
||||
|
@ -89,8 +119,12 @@ def test_include_id():
|
|||
for field in formdef.fields:
|
||||
field.id = formdef.get_new_field_id()
|
||||
formdef.fields[4].id = '10'
|
||||
f2 = assert_import_export_works(formdef, include_id=True)
|
||||
f2 = assert_xml_import_export_works(formdef, include_id=True)
|
||||
assert len(f2.fields) == len(formdef.fields)
|
||||
assert f2.fields[0].id == formdef.fields[0].id
|
||||
assert f2.fields[4].id == formdef.fields[4].id
|
||||
|
||||
f2 = assert_json_import_export_works(formdef, include_id=True)
|
||||
assert len(f2.fields) == len(formdef.fields)
|
||||
assert f2.fields[0].id == formdef.fields[0].id
|
||||
assert f2.fields[4].id == formdef.fields[4].id
|
||||
|
|
|
@ -125,7 +125,7 @@ class Field:
|
|||
def get_admin_attributes(self):
|
||||
return ['label', 'type']
|
||||
|
||||
def export_to_json(self, charset, include_id=False):
|
||||
def export_to_json(self, include_id=False):
|
||||
field = {}
|
||||
if include_id:
|
||||
extra_fields = ['id']
|
||||
|
@ -136,25 +136,16 @@ class Field:
|
|||
continue
|
||||
if hasattr(self, attribute) and getattr(self, attribute) is not None:
|
||||
val = getattr(self, attribute)
|
||||
if type(val) is dict:
|
||||
if not val: continue
|
||||
field[attribute] = {}
|
||||
for k, v in val.items():
|
||||
field[attribute][k] = unicode(v, charset, 'replace')
|
||||
elif type(val) is list:
|
||||
if not val: continue
|
||||
field[attribute] = []
|
||||
for v in val:
|
||||
field[attribute].append(unicode(v, charset, 'replace'))
|
||||
elif type(val) in (str, unicode):
|
||||
if type(val) is unicode:
|
||||
field[attribute] = val
|
||||
else:
|
||||
field[attribute] = unicode(val, charset, 'replace')
|
||||
else:
|
||||
field[attribute] = str(val)
|
||||
field[attribute] = val
|
||||
return field
|
||||
|
||||
def init_with_json(self, elem, include_id=False):
|
||||
if include_id:
|
||||
self.id = elem.get('id')
|
||||
for attribute in self.get_admin_attributes():
|
||||
if attribute in elem:
|
||||
setattr(self, attribute, elem.get(attribute))
|
||||
|
||||
def export_to_xml(self, charset, include_id=False):
|
||||
field = ET.Element('field')
|
||||
if include_id:
|
||||
|
|
119
wcs/formdef.py
119
wcs/formdef.py
|
@ -80,13 +80,13 @@ class FormDef(StorableObject):
|
|||
|
||||
max_field_id = None
|
||||
|
||||
|
||||
# declarations for serialization
|
||||
TEXT_ATTRIBUTES = ('name', 'url_name',
|
||||
'publication_date', 'expiration_date')
|
||||
BOOLEAN_ATTRIBUTES = ('discussion', 'detailed_emails', 'disabled',
|
||||
'only_allow_one', 'allow_drafts', 'disabled_redirection',
|
||||
'always_advertise', 'private_status_and_history')
|
||||
TEXT_ATTRIBUTES = ['name', 'url_name',
|
||||
'publication_date', 'expiration_date',
|
||||
'disabled_redirection',]
|
||||
BOOLEAN_ATTRIBUTES = ['discussion', 'detailed_emails', 'disabled',
|
||||
'only_allow_one', 'allow_drafts',
|
||||
'always_advertise', 'private_status_and_history']
|
||||
|
||||
def migrate(self):
|
||||
changed = False
|
||||
|
@ -386,24 +386,104 @@ class FormDef(StorableObject):
|
|||
|
||||
return d
|
||||
|
||||
def export_to_json(self, include_id=False):
|
||||
def export_to_json(self, include_id=False, indent=None):
|
||||
charset = get_publisher().site_charset
|
||||
root = {}
|
||||
root['name'] = unicode(self.name, charset)
|
||||
if include_id and self.id:
|
||||
root['id'] = str(self.id)
|
||||
if self.category:
|
||||
root['category'] = unicode(self.category.name, charset)
|
||||
for boolean_attribute in self.BOOLEAN_ATTRIBUTES:
|
||||
value = getattr(self, boolean_attribute)
|
||||
if value:
|
||||
value = 'true'
|
||||
else:
|
||||
value = 'false'
|
||||
root[boolean_attribute] = value
|
||||
root['fields'] = []
|
||||
for field in self.fields:
|
||||
root['fields'].append(field.export_to_json(charset=charset, include_id=include_id))
|
||||
root['category_id'] = str(self.category.id)
|
||||
if self.workflow:
|
||||
root['workflow'] = unicode(self.workflow.name, charset)
|
||||
root['workflow_id'] = str(self.workflow.id)
|
||||
|
||||
return json.dumps(root)
|
||||
if self.max_field_id is None and self.fields:
|
||||
self.max_field_id = max([lax_int(x.id) for x in self.fields])
|
||||
|
||||
more_attributes = []
|
||||
if self.max_field_id:
|
||||
more_attributes.append('max_field_id')
|
||||
if self.last_modification_time:
|
||||
more_attributes.append('last_modification_time')
|
||||
if include_id:
|
||||
more_attributes.append('last_modification_user_id')
|
||||
|
||||
for attribute in self.TEXT_ATTRIBUTES + self.BOOLEAN_ATTRIBUTES + more_attributes:
|
||||
if not hasattr(self, attribute):
|
||||
continue
|
||||
root[attribute] = getattr(self, attribute)
|
||||
|
||||
root['fields'] = []
|
||||
if self.fields:
|
||||
for field in self.fields:
|
||||
root['fields'].append(field.export_to_json(include_id=include_id))
|
||||
|
||||
return json.dumps(root, indent=indent)
|
||||
|
||||
def import_from_json(cls, fd, charset=None, include_id=False):
|
||||
if charset is None:
|
||||
charset = get_publisher().site_charset
|
||||
formdef = cls()
|
||||
|
||||
def unicode2str(v):
|
||||
if isinstance(v, dict):
|
||||
return dict([(unicode2str(k), unicode2str(v)) for k, v in v.items()])
|
||||
elif isinstance(v, list):
|
||||
return [unicode2str(x) for x in v]
|
||||
elif isinstance(v, unicode):
|
||||
return v.encode(charset)
|
||||
else:
|
||||
return v
|
||||
|
||||
# we have to make sure all strings are str object, not unicode.
|
||||
value = unicode2str(json.load(fd))
|
||||
|
||||
if include_id and 'id' in value:
|
||||
formdef.id = value.get('id')
|
||||
|
||||
if include_id and 'category_id' in value:
|
||||
formdef.category_id = value.get('category_id')
|
||||
elif 'category' in value:
|
||||
category = value.get('category')
|
||||
for c in Category.select():
|
||||
if c.name == category:
|
||||
formdef.category_id = c.id
|
||||
break
|
||||
|
||||
if include_id and 'workflow_id' in value:
|
||||
formdef.workflow_id = value.get('workflow_id')
|
||||
elif 'workflow' in value:
|
||||
workflow = value.get('workflow')
|
||||
for w in Workflow.select():
|
||||
if w.name == workflow:
|
||||
formdef.workflow_id = w.id
|
||||
break
|
||||
|
||||
more_attributes = ['max_field_id', 'last_modification_time',
|
||||
'last_modification_user_id']
|
||||
for attribute in cls.TEXT_ATTRIBUTES + cls.BOOLEAN_ATTRIBUTES + more_attributes:
|
||||
if attribute in value:
|
||||
setattr(formdef, attribute, value.get(attribute))
|
||||
|
||||
formdef.fields = []
|
||||
for i, field in enumerate(value.get('fields', [])):
|
||||
try:
|
||||
field_o = fields.get_field_class_by_type(field.get('type'))()
|
||||
except KeyError:
|
||||
raise ValueError()
|
||||
field_o.init_with_json(field, include_id=include_id)
|
||||
if not field_o.id:
|
||||
# this assumes all fields will have id, or none of them
|
||||
field_o.id = str(i)
|
||||
formdef.fields.append(field_o)
|
||||
|
||||
if formdef.fields and not formdef.max_field_id:
|
||||
formdef.max_field_id = max([lax_int(x.id) for x in formdef.fields])+1
|
||||
|
||||
return formdef
|
||||
import_from_json = classmethod(import_from_json)
|
||||
|
||||
def export_to_xml(self, include_id=False):
|
||||
charset = get_publisher().site_charset
|
||||
|
@ -437,6 +517,9 @@ class FormDef(StorableObject):
|
|||
if include_id:
|
||||
elem.attrib['workflow_id'] = str(self.workflow.id)
|
||||
|
||||
if self.max_field_id is None and self.fields:
|
||||
self.max_field_id = max([lax_int(x.id) for x in self.fields])
|
||||
|
||||
if self.max_field_id:
|
||||
ET.SubElement(root, 'max_field_id').text = str(self.max_field_id)
|
||||
|
||||
|
|
Loading…
Reference in New Issue