WTForms:FieldList 的 FormField 无法加载嵌套数据
我在一个字段列表里有一个自定义字段,叫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)
当我提交这个表单时,它会保存到一个对象里,像这样:
document = {
'title': unicode,
'description': unicode,
'manager': unicode,
'locations': [{
'id': uuid.UUID,
'title': unicode,
'location': {'coordinates':[float], 'text':unicode}
}],
}
但是当我尝试在一个GET处理程序中加载数据到表单时,除了locations以外的所有内容都能正常加载:
f = form(MultiDict(document))
f.locations.data
>> {'id':'','title':'','location':''}
我做了一些调试,发现WTForms在把文档的数据加载到表单时,会查找'locations-0-location'这个键,但MultiDict()里并没有这个键。MultiDict并不会把字典列表转换成'locations-i-...'这样的键。
那么,针对这种嵌套的数据结构,正确的WTForm写法应该是什么呢?
3 个回答
1
我觉得答案在文档的这一部分,关于.process()
这个方法:
因为BaseForm在创建的时候并不会直接接收数据,所以你必须调用这个方法来给里面的字段提供表单数据。
你应该使用:
f = form()
f.process(data=MultiDict(document))
而不是:
f = form(MultiDict(document))
1
我也遇到过同样的问题,后来我通过把列表转换成一个带有前缀的字典来解决了这个问题。
大概是这样的:
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()})
4
使用WTFORMS 2.1
这里是数据:
document = {
'title': unicode,
'description': unicode,
'manager': unicode,
'locations': [{
'id': uuid.UUID,
'title': unicode,
'location': {'coordinates':[float], 'text':unicode}
}],
}
你可以用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)
试试这个:
f = ProjectForm()
f.process(data=document)
f.locations.data