WTForms:我是否可以一次性将对象绑定到表单,而不是单独绑定每个字段?

1 投票
1 回答
832 浏览
提问于 2025-04-18 09:49

我正在使用Google App Engine写一个应用程序。之前在处理POST请求时,我是这样绑定提交的数据的:

form_data = {
    'fname': self.form.fname.data.strip(),
    'lname': self.form.lname.data.strip(),
    'phone': self.form.phone.data.strip(),
    'email': self.form.email.data.strip().lower(),
    ... (lots more lines like this on long forms)

后来我发现了一个叫populate_obj()的方法,它让我可以把这个过程简化成一行代码。

self.form.populate_obj(customer)

现在我想知道有没有办法反过来做?我从存储中取出了一个Customer对象,想把它绑定到表单上。下面的代码可以运行,但写起来有点麻烦。

customer = # get customer from storage

self.form.fname.data = customer.fname
self.form.lname.data = customer.lname
self.form.phone.data = customer.phone
self.form.email.data = customer.email
... (lots more lines like this on long forms)

有没有类似populate_form()的方法,可以让我一次性把这个对象绑定到表单,而不是一个字段一个字段地绑定?

1 个回答

3

Form类的构造函数有三个关键字参数。

  • formdata:这个参数用来获取表单的数据,它会把数据转换成合适的格式,并把这些数据绑定到表单上。
  • data:这个参数接收一个叫做MultiDict的对象,里面的键对应表单的各个字段,它不会进行数据转换,只是把数据绑定到表单上。
  • obj:这个参数接收一个对象,这个对象的属性和表单的字段相对应,它会把这些属性的值绑定到正确的表单字段上。

如果你想实现你所描述的功能,只需要在创建表单时,把你的对象传给obj这个参数就可以了。

代码示例

from collections import namedtuple                    

from wtforms import Form                              
from wtforms import IntegerField                      
from wtforms import TextField                         

# create some People                                  
Person= namedtuple('person', ['id', 'fname', 'lname'])
p1 = Person(1, 'bob', 'barker')                       

class TestForm(Form):                                 
    id = IntegerField('id')                           
    fname =TextField('lname')                         
    lname =TextField('lname')                         

# Build form and print                                
test_form = TestForm(obj=p1)                          

# test print                                          
print(test_form.id)                                   
print(test_form.fname)                                
print(test_form.lname)                                                                                        
print(test_form.data)   

测试打印

<input id="id" name="id" type="text" value="1">
<input id="fname" name="fname" type="text" value="bob">
<input id="lname" name="lname" type="text" value="barker">
{'lname': 'barker', 'id': 1, 'fname': 'bob'}

你需要注意的唯一一点是,obj不会进行类型转换。所以如果你把字符串'1'传给一个IntegerField,然后尝试验证,验证会失败。

撰写回答