formdefs: keep track of allocated field ids (#3363)

This commit is contained in:
Frédéric Péters 2013-07-30 09:17:21 +02:00
parent 95b012f7d3
commit 8163d7e267
5 changed files with 90 additions and 57 deletions

View File

@ -405,3 +405,57 @@ def test_urlname_change():
assert formdef.url_name == 'tests'
assert data_class.count() == 1
@postgresql
def test_sql_table_add_and_remove_fields():
test_formdef = FormDef()
test_formdef.name = 'tests and and remove fields'
test_formdef.fields = []
test_formdef.store()
assert test_formdef.table_name is not None
data_class = test_formdef.data_class(mode='sql')
assert data_class.count() == 0
test_formdef.fields = [
fields.StringField(label='string'),
fields.EmailField(label='email'),
]
for field in test_formdef.fields:
if field.id is None:
field.id = test_formdef.get_new_field_id()
test_formdef.store()
test_formdef.fields.append(
fields.ItemField(label='item', items=('apple', 'pear', 'peach', 'apricot')))
test_formdef.fields[-1].id = test_formdef.get_new_field_id()
test_formdef.store()
data_class = test_formdef.data_class(mode='sql')
data_class.select()
previous_id = test_formdef.fields[-1].id
test_formdef.fields = test_formdef.fields[:-1]
test_formdef.store()
data_class = test_formdef.data_class(mode='sql')
data_class.select()
test_formdef.fields.append(fields.StringField(label='item'))
test_formdef.fields[-1].id = test_formdef.get_new_field_id()
test_formdef.store()
assert test_formdef.fields[-1].id != previous_id
data_class = test_formdef.data_class(mode='sql')
data_class.select()
test_formdef.fields = test_formdef.fields[:-1]
test_formdef.fields.append(
fields.ItemField(label='item', items=('apple', 'pear', 'peach', 'apricot')))
test_formdef.fields[-1].id = test_formdef.get_new_field_id()
test_formdef.store()
data_class = test_formdef.data_class(mode='sql')
data_class.select()

View File

@ -160,14 +160,8 @@ class FieldDefPage(Directory):
field_pos = self.objectdef.fields.index(self.field)
fields = self.objectdef.fields
new_field = copy.copy(self.field)
def lax_int(s):
try:
return int(s)
except (ValueError, TypeError):
return -1
# allocate a new id
id = str(max([lax_int(x.id) for x in self.objectdef.fields]) + 1)
new_field.id = id
new_field.id = self.objectdef.get_new_field_id()
fields.insert(field_pos+1, new_field)
self.objectdef.store()
if self.page_no:
@ -372,12 +366,6 @@ class FieldsDirectory(Directory):
get_session().message = ('error', _('Submitted form was not filled properly.'))
return redirect('.')
def lax_int(s):
try:
return int(s)
except (ValueError, TypeError):
return -1
try:
page_no = int(form.get_widget('page_no').parse())
except (TypeError, ValueError):
@ -399,22 +387,15 @@ class FieldsDirectory(Directory):
insertion_point = len(self.objectdef.fields)
if form.get_widget('label').parse() and form.get_widget('type').parse():
if self.objectdef.fields:
id = str(max([lax_int(x.id) for x in self.objectdef.fields]) + 1)
else:
id = '1'
self.objectdef.fields.insert(insertion_point,
fields.get_field_class_by_type(form.get_widget('type').parse())(
label = form.get_widget('label').parse(),
type = form.get_widget('type').parse(),
id = id))
id =self.objectdef.get_new_field_id()))
elif form.get_widget('form').parse():
formdef = FormDef.get(form.get_widget('form').parse())
for j, field in enumerate(formdef.fields):
if self.objectdef.fields:
field.id = str(max([lax_int(x.id) for x in self.objectdef.fields]) + 1)
else:
field.id = '1'
field.id = self.objectdef.get_new_field_id()
self.objectdef.fields.insert(insertion_point+j, field)
else:
get_session().message = ('error', _('Submitted form was not filled properly.'))

View File

@ -138,35 +138,8 @@ class FormDefUI:
else:
formdef.roles = []
def lax_int(s):
try:
return int(s)
except ValueError:
return -1
if not formdef.fields:
formdef.fields = []
if form.get_widget('fields'):
new_fields = []
for field in form.get_widget('fields').parse():
if not field['label']:
if field['id']:
formdef.fields = [x for x in formdef.fields if x.id != field['id']]
continue
if field['id']:
form_field = [x for x in formdef.fields if x.id == field['id']][0]
else:
form_field = FormField()
if formdef.fields or new_fields:
form_field.id = str(max([
lax_int(x.id) for x in formdef.fields + new_fields]) + 1)
else:
form_field.id = '1'
form_field.label = field['label']
form_field.type = field['type']
new_fields.append(form_field)
formdef.fields = new_fields
formdef.store()
@ -1076,11 +1049,6 @@ class FormsDirectory(AccessControlled, Directory):
form = formdefui.new_form_ui()
if form.get_widget('cancel').parse():
return redirect('.')
redo = False
if form.get_widget('fields') and \
form.get_widget('fields').get_widget('add_element').parse():
form.clear_errors()
redo = True
if form.is_submitted() and not form.has_errors() and not redo:
try:

View File

@ -53,6 +53,13 @@ class FormField:
self.real_field = fields.get_field_class_by_type(type)(**dict)
def lax_int(s):
try:
return int(s)
except (ValueError, TypeError):
return -1
class FormDef(StorableObject):
_names = 'formdefs'
_indexes = ['url_name']
@ -84,6 +91,8 @@ class FormDef(StorableObject):
last_modification_time = None
last_modification_user_id = None
max_field_id = None
def migrate(self):
changed = False
@ -147,6 +156,10 @@ class FormDef(StorableObject):
self.table_name = sql.get_formdef_table_name(self)
changed = True
if self.max_field_id is None and self.fields:
self.max_field_id = max([lax_int(x.id) for x in self.fields])
changed = True
if changed:
self.store()
@ -171,6 +184,14 @@ class FormDef(StorableObject):
setattr(sys.modules['wcs.formdef'], self.url_name.title(), cls)
return cls
def get_new_field_id(self):
if self.max_field_id is None:
field_id = 1
else:
field_id = self.max_field_id + 1
self.max_field_id = field_id
return str(field_id)
def get_new_url_name(self):
new_url_name = simplify(self.name)
base_new_url_name = new_url_name
@ -377,7 +398,6 @@ class FormDef(StorableObject):
return json.dumps(root)
def export_to_xml(self, include_id=False):
charset = get_publisher().site_charset
root = ET.Element('formdef')
@ -393,7 +413,9 @@ class FormDef(StorableObject):
value = 'true'
else:
value = 'false'
ET.SubElement(root, boolean_attribute).text = value
ET.SubElement(root, boolean_attribute).text = value
if self.max_field_id:
ET.SubElement(root, 'max_field_id').text = str(self.max_field_id)
only_allow_one = False
allow_drafts = False
fields = ET.SubElement(root, 'fields')
@ -426,8 +448,15 @@ class FormDef(StorableObject):
field_o.init_with_xml(field, charset, 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)
field_o.id = str(i+1)
formdef.fields.append(field_o)
value = tree.find('max_field_id')
if value is not None:
formdef.max_field_id = int(value)
else:
formdef.max_field_id = max([lax_int(x.id) for x in formdef.fields])+1
if tree.find('category') is not None:
category = tree.find('category').text.encode(charset)
cats = Category.select()

View File

@ -142,6 +142,7 @@ def do_formdef_tables(formdef):
# add new fields
for field in formdef.fields:
assert field.id is not None
sql_type = SQL_TYPE_MAPPING.get(field.key, 'varchar')
if sql_type is None:
continue