WTForms:如果数据存在,则用数据填充表单

问题描述 投票:0回答:3

我有以下 Flask-WTF 形式:

class PersonForm(FlaskForm):
    name = StringField('Name', validators=[DataRequired()])
    age = IntegerField('Age', validators=[NumberRange(min=0)], render_kw={'type': 'number'})
    educated = BooleanField('Educated', render_kw={'type': 'checkbox'})

我知道我可以通过将值传递到表单中来预填充表单,如下所示:

form = PersonForm(name='Johnny', age=25, educated=True)

我注意到有一种更好的方法可以通过将对象注入到表单中来实现此目的(参考herehere)。我已经尝试过以下方法,但是,它不起作用。我哪里出错了(该对象应该是字典以外的东西吗)?

person = {'name': 'Johnny', 'age': 25, 'educated'=True}
form = PersonForm(obj=person)

请注意,这些预先填充的值来自数据库。有些值已定义,有些则未定义。例如,另一个“人”可能看起来像

{'name': 'Jessica', 'educated': True}
(在这种情况下,年龄字段将为空)。

python forms wtforms flask-wtforms
3个回答
8
投票

我认为您想改用

data
参数,如 this 文档中所述:

表格类

类 wtforms.form.Form

声明式表单基类。 施工

__init__(formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs)
    Parameters:   

...

data – 接受数据字典。仅当 formdata 和 obj 不存在时才使用。 ...

演示:

>>> from wtforms import Form, StringField, validators
>>>
>>> class UsernameForm(Form):
    username = StringField('Username', [validators.Length(min=5)], default=u'test')
    email = StringField('Email', [validators.email(message='Check your email')], default=u'[email protected]')
>>>
>>> person = {'username': 'Johnny', 'email': '[email protected]'}
>>>
>>> form = UsernameForm(data=person)
>>> 
>>> form.username.data
'Johnny'
>>> 
>>> form.email.data
'[email protected]'

它也可以与

formdata
参数一起使用,但您必须传递
MultiDict
对象:

>>> from werkzeug.datastructures import MultiDict
>>> 
>>> b = MultiDict(person)
>>> 
>>> b
MultiDict([('email', '[email protected]'), ('username', 'Johnny')])
>>> 
>>> 
>>> form2 = UsernameForm(formdata=b)
>>> form2.username.data
'Johnny'
>>> form2.email.data
'[email protected]'
>>> 

也将

**kwargs
作为常规字典传递:

>> form3 = UsernameForm(**person)
>>> 
>>> form3.username.data
'Johnny'
>>> 
>>> form3.email.data
'[email protected]'

编辑:回复OP关于使用

obj
参数的评论并引用文档:

 __init__(formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs)

参数:
...

obj – 如果 formdata 为空或未提供,则检查此对象是否有与表单字段名称匹配的属性,该属性将用于字段值。

...

这意味着您需要传入一个属性名称与表单属性名称相同的对象,如下所示:

>>> class Person:
        username = 'Johny'
        email = '[email protected]'

>>> 
>>> form = UsernameForm(obj=Person)
>>> 
>>> form.data
{'email': '[email protected]', 'username': 'Johny'}

0
投票

你需要一个MultiDict

>>> a
{'hello': 'data', 'more': 'data'}
>>> from werkzeug.datastructures import MultiDict
>>> b=MultiDict(a)
>>> b
MultiDict([('hello', 'data'), ('more', 'data')])
>>> 

0
投票

我使用会话变量将 POST 表单中的数据传递回 GET 上的模板,以便在 Post 或用户页面刷新出现错误时呈现表单用户填充的值 - 以免清除表单并惹恼用户。

我必须直接将完整的 form.request 传递回模板,并从该字典中索引出值,以便在 html 模板中预填充数据,因为我在 python Flask 应用程序中没有定义表单字段的类。其他更清晰的答案使用表单类并将其传递给 html - 我的设置不太好;)

相关 下面的代码 - 忽略 app.py 中不相关的部分:

if ( request.method == 'POST'):
    session['last_request_data']= request.form
if (form_error):
    return render_template('home.html', prefill_data=session['last_request_data'])

if ( request.method == 'GET'):

if(会话中的“last_request_data”): print("使用会话中的最后数据预填充表单")
返回 render_template('home.html', prefill_data=session['last_request_data']) 别的: print(“第一次页面加载 - 没有数据要预填充 - 呈现空表单”)
返回 render_template('home.html')

然后在 html 模板中 - 每次我尝试使用表单中的键预填充值时,我都必须检查是否传递了任何预填充数据...

            <input type="text" name="player1name" {% if prefill_data %} value="{{ prefill_data.get("player1name") }}"{% endif %}/> 
© www.soinside.com 2019 - 2024. All rights reserved.