I have the following Flask-WTF form:
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'})
I know I can pre-populate the form by passing values into the form like so:
form = PersonForm(name='Johnny', age=25, educated=True)
I've noticed there's a better way to do this by injecting an object into the form (references here and here). I've tried the following, however, it doesn't work. Where am I going wrong (is the object supposed to be something other than a dictionary)?
person = {'name': 'Johnny', 'age': 25, 'educated'=True}
form = PersonForm(obj=person)
Note these pre-populated values come from a database. Some values are defined while some aren't. For example, another "person" may look like {'name': 'Jessica', 'educated': True}
(the age field will be empty in this case).
I think you want to use the data
parameter instead, as mentioned in this documentation:
The Form class
class wtforms.form.Form
Declarative Form base class. Construction
__init__(formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs) Parameters:
...
data – Accept a dictionary of data. This is only used if formdata and obj are not present. ...
Demonstration:
>>> 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'test@domain.com')
>>>
>>> person = {'username': 'Johnny', 'email': 'Johny@domain.net'}
>>>
>>> form = UsernameForm(data=person)
>>>
>>> form.username.data
'Johnny'
>>>
>>> form.email.data
'Johny@domain.net'
It does work with the formdata
parameter as well, but you will have to pass a MultiDict
object:
>>> from werkzeug.datastructures import MultiDict
>>>
>>> b = MultiDict(person)
>>>
>>> b
MultiDict([('email', 'Johny@domain.net'), ('username', 'Johnny')])
>>>
>>>
>>> form2 = UsernameForm(formdata=b)
>>> form2.username.data
'Johnny'
>>> form2.email.data
'Johny@domain.net'
>>>
Also with **kwargs
passed as a regular dictionary:
>> form3 = UsernameForm(**person)
>>>
>>> form3.username.data
'Johnny'
>>>
>>> form3.email.data
'Johny@domain.net'
EDIT: in reply to OP's comment concerning the use of obj
parameters and quoting from docs:
__init__(formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs)
Parameters:
...obj – If formdata is empty or not provided, this object is checked for attributes matching form field names, which will be used for field values.
...
That means you need to pass in an object with attribute names same as your forms' attribute name, as follows:
>>> class Person:
username = 'Johny'
email = 'Johny@domain.net'
>>>
>>> form = UsernameForm(obj=Person)
>>>
>>> form.data
{'email': 'Johny@domain.net', 'username': 'Johny'}