Forms¶
Forms provide the highest level API in WTForms. They contain your field definitions, delegate validation, take input, aggregate errors, and in general function as the glue holding everything together.
The Form class¶
- class wtforms.form.Form[source]¶
Declarative Form base class.
Construction
- __init__(formdata=None, obj=None, prefix='', data=None, meta=None, **kwargs)[source]¶
- Parameters
formdata – Input data coming from the client, usually
request.form
or equivalent. Should provide a “multi dict” interface to get a list of values for a given key, such as what Werkzeug, Django, and WebOb provide.obj – Take existing data from attributes on this object matching form field attributes. Only used if
formdata
is not passed.prefix – If provided, all fields will have their name prefixed with the value. This is for distinguishing multiple forms on a single page. This only affects the HTML name for matching input data, not the Python name for matching existing data.
data – Take existing data from keys in this dict matching form field attributes.
obj
takes precedence if it also has a matching attribute. Only used ifformdata
is not passed.meta – A dict of attributes to override on this form’s
meta
instance.extra_filters – A dict mapping field attribute names to lists of extra filter functions to run. Extra filters run after filters passed when creating the field. If the form has
filter_<fieldname>
, it is the last extra filter.kwargs – Merged with
data
to allow passing existing data as parameters. Overwrites any duplicate keys indata
. Only used ifformdata
is not passed.
Initialize a Form. This is usually done in the context of a view/controller in your application. When a Form is constructed, the fields populate their input based on the formdata, obj, and kwargs.
Note Backing-store objects and kwargs are both expected to be provided with the values being already-coerced datatypes. WTForms does not check the types of incoming object-data or coerce them like it will for formdata as it is expected this data is defaults or data from a backing store which this form represents. See the section on using Forms for more information.
Properties
- data¶
A dict containing the data for each field.
Note that this is generated each time you access the property, so care should be taken when using it, as it can potentially be very expensive if you repeatedly access it. Typically used if you need to iterate all data in the form. If you just need to access the data for known fields, you should use form.<field>.data, not this proxy property.
- errors¶
A dict containing a list of errors for each field. Empty if the form hasn’t been validated, or there were no errors.
If present, the key
None
contains the content ofform_errors
.
- form_errors¶
A list of form-level errors. Those are errors that does not concern a particuliar field, but the whole form consistency. Those errors are often set when overriding
validate()
.
- meta¶
This is an object which contains various configuration options and also ability to customize the behavior of the form. See the class Meta doc for more information on what can be customized with the class Meta options.
Methods
- validate(extra_validators=None)[source]¶
Validate the form by calling
validate
on each field. ReturnsTrue
if validation passes.If the form defines a
validate_<fieldname>
method, it is appended as an extra validator for the field’svalidate
.- Parameters
extra_validators – A dict mapping field names to lists of extra validator methods to run. Extra validators run after validators passed when creating the field. If the form has
validate_<fieldname>
, it is the last extra validator.
- populate_obj(obj)¶
Populates the attributes of the passed obj with data from the form’s fields.
- Note
This is a destructive operation; Any attribute with the same name as a field will be overridden. Use with caution.
One common usage of this is an edit profile view:
def edit_profile(request): user = User.objects.get(pk=request.session['userid']) form = EditProfileForm(request.POST, obj=user) if request.POST and form.validate(): form.populate_obj(user) user.save() return redirect('/home') return render_to_response('edit_profile.html', form=form)
In the above example, because the form isn’t directly tied to the user object, you don’t have to worry about any dirty data getting onto there until you’re ready to move it over.
- __iter__()¶
Iterate form fields in creation order.
{% for field in form %} <tr> <th>{{ field.label }}</th> <td>{{ field }}</td> </tr> {% endfor %}
- __contains__(name)¶
Returns True if the named field is a member of this form.
Defining Forms¶
To define a form, one makes a subclass of Form
and defines the fields
declaratively as class attributes:
class MyForm(Form):
first_name = StringField('First Name', validators=[validators.input_required()])
last_name = StringField('Last Name', validators=[validators.optional()])
Field names can be any valid python identifier, with the following restrictions:
Field names are case-sensitive.
Field names may not begin with “_” (underscore)
Field names may not begin with “validate”
Form Inheritance¶
Forms may subclass other forms as needed. The new form will contain all fields of the parent form, as well as any new fields defined on the subclass. A field name re-used on a subclass causes the new definition to obscure the original.
class PastebinEdit(Form):
language = SelectField('Programming Language', choices=PASTEBIN_LANGUAGES)
code = TextAreaField()
class PastebinEntry(PastebinEdit):
name = StringField('User Name')
In-line Validators and Filters¶
In order to provide custom validation for a single field without needing to write a one-time-use validator, validation can be defined inline by defining a method with the convention validate_fieldname:
class SignupForm(Form):
age = IntegerField('Age')
def validate_age(form, field):
if field.data < 13:
raise ValidationError("We're sorry, you must be 13 or older to register")
The same principle applies for filters with the convention filter_fieldname:
class SignupForm(Form):
name = StringField('name')
def filter_name(form, field):
return field.strip()
Note that filters are applied after processing the default and incoming data, but before validation.
Using Forms¶
A form is most often constructed in the controller code for handling an action, with the form data wrapper from the framework passed to its constructor, and optionally an ORM object. A typical view begins something like:
def edit_article(request):
article = Article.get(...)
form = MyForm(request.POST, article)
A typical CRUD view has a user editing an object that needs various fields updated. The Form would have fields describing the fields to be updated and the validation rules, where the attribute names of the fields match those of the attribute names on the object. The second parameter to the Form, the obj parameter, is used to populate form defaults on the initial view.
Note
While we did pass an object as the data source, this object data is only used if there is no POST data. If there is any POST data at all, then the object data is ignored. This is done for security and consistency reasons.
This pattern is mostly a convenience since most application controllers don’t separate GET and POST requests into separate view methods.
The constructed form can then validate any input data and generate errors if invalid. Typically, the validation pattern in the view looks like:
if request.POST and form.validate():
form.populate_obj(article)
article.save()
return redirect('/articles')
Note that we have it so validate()
is only called if there is
POST data. The reason we gate the validation check this way is that when
there is no POST data (such as in a typical CRUD form) we don’t want to
cause validation errors.
Inside the gated block, we call populate_obj()
to copy the data
onto fields on the ‘article’ object. We also then redirect after a successful
completion. The reason we redirect after the post is a best-practice associated
with the Post/Redirect/Get
design pattern.
If there is no POST data, or the data fails to validate, then the view “falls through” to the rendering portion. The Form object can be passed into the template and its attributes can be used to render the fields and also for displaying errors:
return render('edit.html', form=form, article=article)
So there we have a full simple “edit object” page setup which illustrates a best-practice way of using WTForms. This is by no means the only way to use WTForms, but just an illustration of how the various features work.
Here is the full code for the view we just made:
def edit_article(request):
article = Article.get(...)
form = MyForm(request.POST, article)
if request.POST and form.validate():
form.populate_obj(article)
article.save()
return redirect('/articles')
return render('edit.html', form=form, article=article)
Low-Level API¶
Warning
This section is provided for completeness; and is aimed at authors of complementary libraries and those looking for very special behaviors. Don’t use BaseForm unless you know exactly why you are using it.
For those looking to customize how WTForms works, for libraries or special
applications, it might be worth using the BaseForm
class. BaseForm is
the parent class of Form
, and most of the implementation
logic from Form is actually handled by BaseForm.
The major difference on the surface between BaseForm and Form is that fields are not defined declaratively on a subclass of BaseForm. Instead, you must pass a dict of fields to the constructor. Likewise, you cannot add fields by inheritance. In addition, BaseForm does not provide: sorting fields by definition order, or inline validate_foo validators. Because of this, for the overwhelming majority of uses we recommend you use Form instead of BaseForm in your code.
What BaseForm provides is a container for a collection of fields, which it will bind at instantiation, and hold in an internal dict. Dict-style access on a BaseForm instance will allow you to access (and modify) the enclosed fields.
- class wtforms.form.BaseForm[source]¶
Base Form Class. Provides core behaviour like field construction, validation, and data and error proxying.
Construction
- __init__(fields, prefix='', meta=<DefaultMeta>)[source]¶
- Parameters
fields – A dict or sequence of 2-tuples of partially-constructed fields.
prefix – If provided, all fields will have their name prefixed with the value.
meta – A meta instance which is used for configuration and customization of WTForms behaviors.
form = BaseForm({ 'name': StringField(), 'customer.age': IntegerField("Customer's Age") })
Because BaseForm does not require field names to be valid identifiers, they can be most any python string. We recommend keeping it simple to avoid incompatibility with browsers and various form input frameworks where possible.
Properties
- errors¶
see
Form.errors
Methods
- process(formdata=None, obj=None, data=None, extra_filters=None, **kwargs)[source]¶
Process default and input data with each field.
- Parameters
formdata – Input data coming from the client, usually
request.form
or equivalent. Should provide a “multi dict” interface to get a list of values for a given key, such as what Werkzeug, Django, and WebOb provide.obj – Take existing data from attributes on this object matching form field attributes. Only used if
formdata
is not passed.data – Take existing data from keys in this dict matching form field attributes.
obj
takes precedence if it also has a matching attribute. Only used ifformdata
is not passed.extra_filters – A dict mapping field attribute names to lists of extra filter functions to run. Extra filters run after filters passed when creating the field. If the form has
filter_<fieldname>
, it is the last extra filter.kwargs – Merged with
data
to allow passing existing data as parameters. Overwrites any duplicate keys indata
. Only used ifformdata
is not passed.
Since BaseForm does not take its data at instantiation, you must call this to provide form data to the enclosed fields. Accessing the field’s data before calling process is not recommended.
- validate(extra_validators=None)[source]¶
Validates the form by calling validate on each field.
- Parameters
extra_validators – If provided, is a dict mapping field names to a sequence of callables which will be passed as extra validators to the field’s validate method.
Returns True if no errors occur.
- __iter__()[source]¶
Iterate form fields in creation order.
Unlike
Form
, fields are not iterated in definition order, but rather in whatever order the dict decides to yield them.
- __setitem__(name, value)[source]¶
Bind a field to this form.
form['openid.name'] = StringField()
Fields can be added and replaced in this way, but this must be done before
process()
is called, or the fields will not have the opportunity to receive input data. Similarly, changing fields aftervalidate()
will have undesired effects.
- __delitem__(name)[source]¶
Remove a field from this form.
The same caveats apply as with
__setitem__()
.