Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WTForms: FieldList of FormField can't load nested data

I have a custom field inside a FormField inside a FieldList: locations

class LocationForm(Form):
    id = HiddenField('id')
    title = StringField(_l('Title'), [Required()])
    location = CoordinatesField(_l('Coordinates'))

class ProjectForm(Form):
    title = StringField(_l('Title'))
    manager = StringField(_l('Manager'))
    description = StringField(_l('Description'))
    locations = FieldList(FormField(LocationForm), min_entries=1)

This form when submited is saved to an object like this:

document = {
    'title': unicode,
    'description': unicode,
    'manager': unicode,
    'locations': [{
        'id': uuid.UUID,
        'title': unicode,
        'location': {'coordinates':[float], 'text':unicode}
        }],
    }

When I try to load the data in to the form for a GET handler, everything but the locations loads fine:

f = form(MultiDict(document))
f.locations.data
>> {'id':'','title':'','location':''}

I did some debugging and found that WTForms while loading the document's data in to the form searches for 'locations-0-location' but MultiDict() but that keys doesn't exists. MultiDict doesn't convert a list of dictionaries to the key 'locations-i-...'.

What is the right way to make a WTForm for such a nested data structure?

like image 243
user221356 Avatar asked Aug 08 '14 12:08

user221356


2 Answers

with WTFORMS 2.1

the data:

document = {
    'title': unicode,
    'description': unicode,
    'manager': unicode,
    'locations': [{
        'id': uuid.UUID,
        'title': unicode,
        'location': {'coordinates':[float], 'text':unicode}
        }],
    }

you set the data structure with WTFORMS:

class LocationForm(Form):
    id = HiddenField('id')
    title = StringField(_l('Title'), [Required()])
    location = CoordinatesField(_l('Coordinates'))

class ProjectForm(Form):
    title = StringField(_l('Title'))
    manager = StringField(_l('Manager'))
    description = StringField(_l('Description'))
    locations = FieldList(FormField(LocationForm), min_entries=1)

try this:

f = ProjectForm()
f.process(data=document)
f.locations.data
like image 177
Alex W. Avatar answered Oct 24 '22 15:10

Alex W.


I had the same problem and was able to sort it by flattening the list to a dict with the added prefix.

Something like:

document = {
    'title': unicode,
    'description': unicode,
    'manager': unicode,
}

locations = [{
    'id': uuid.UUID,
    'title': unicode,
    'location': {'coordinates':[float], 'text':unicode}
}]

document.update({'locations-%s-%s' % (num, key): val for num, l in enumerate(locations) for key, val in l.items()})
like image 32
s-block Avatar answered Oct 24 '22 17:10

s-block