Widgets

Widgets are classes whose purpose are to render a field to its usable representation, usually XHTML. When a field is called, the default behaviour is to delegate the rendering to its widget. This abstraction is provided so that widgets can easily be created to customize the rendering of existing fields.

Note All built-in widgets will return upon rendering a “HTML-safe” unicode string subclass that many templating frameworks (Jinja, Mako, Genshi) will recognize as not needing to be auto-escaped.

Built-in widgets

class wtforms.widgets.ColorInput(input_type=None)[source]

Render an <input type=”color”>.

class wtforms.widgets.Button(input_type=None)[source]

Render a <button> element.

Pass label= when rendering to override the visible button text. The label is HTML-escaped; pass a markupsafe.Markup instance to embed HTML (icons, formatted text) in the button content.

class wtforms.widgets.CheckboxInput(input_type=None)[source]

Render an <input type=”checkbox”>.

The checked HTML attribute is set if the field’s data is a non-false value.

class wtforms.widgets.DateTimeInput(input_type=None)[source]

Render an <input type="datetime"> control.

This is a legacy HTML input type. For modern browser support, prefer DateTimeLocalInput.

class wtforms.widgets.DateTimeLocalInput(input_type=None)[source]

Render an <input type=”datetime-local”>.

class wtforms.widgets.DateInput(input_type=None)[source]

Render a <input type=”date”>.

class wtforms.widgets.EmailInput(input_type=None)[source]

Render an <input type=”email”>.

class wtforms.widgets.FileInput(multiple=False)[source]

Render an <input type=”file”>.

Parameters:

multiple – allow choosing multiple files

class wtforms.widgets.HiddenInput(*args, **kwargs)[source]

Render an <input type=”hidden”>.

class wtforms.widgets.Input(input_type=None)[source]

Render a basic <input> field.

This is used as the basis for most of the other input fields.

By default, the _value() method will be called upon the associated field to provide the value= HTML attribute.

class wtforms.widgets.ListWidget(html_tag='ul', prefix_label=True)[source]

Render a list of fields as a <ul> or <ol>.

This is used for fields which encapsulate many inner fields as subfields. The widget will try to iterate the field to get access to the subfields and call them to render them.

If prefix_label is set, the subfield’s label is printed before the field, otherwise afterwards. The latter is useful for iterating radios or checkboxes.

class wtforms.widgets.MonthInput(input_type=None)[source]

Render an <input type=”month”>.

class wtforms.widgets.NumberInput(step=None, min=None, max=None)[source]

Render an <input type=”number”>.

class wtforms.widgets.PasswordInput(hide_value=True)[source]

Render an <input type=”password”>.

For security purposes, this field will not reproduce the value on a form submit by default. To have the value filled in, set hide_value to False.

class wtforms.widgets.RadioInput(input_type=None)[source]

Render a single <input type=”radio”> button.

This widget is most commonly used in conjunction with ListWidget or some other listing, as singular radio buttons are not very useful.

class wtforms.widgets.RangeInput(step=None, min=None, max=None)[source]

Render an <input type=”range”>.

class wtforms.widgets.SubmitInput(input_type=None)[source]

Renders an <input type=”submit”>.

The field’s label is used as the text of the submit button instead of the data on the field.

class wtforms.widgets.SearchInput(input_type=None)[source]

Render an <input type=”search”>.

class wtforms.widgets.Select(multiple=False)[source]

Renders a <select> field.

If multiple is True, then the size property should be specified on rendering to make the field useful.

The field must provide an iter_choices() method which the widget will call on rendering; this method must yield Choice.

class wtforms.widgets.TableWidget(with_table_tag=True)[source]

Render a list of fields as a <table>.

If with_table_tag is True, then an enclosing <table> is placed around the rows.

Hidden fields will not be displayed with a row, instead the field will be pushed into a subsequent table row to ensure XHTML validity. Hidden fields at the end of the field list will appear outside the table.

class wtforms.widgets.TelInput(input_type=None)[source]

Render an <input type=”tel”>.

class wtforms.widgets.TextArea[source]

Renders a multi-line <textarea>.

rows and cols ought to be passed as keyword args when rendering.

class wtforms.widgets.TextInput(input_type=None)[source]

Render a single-line <input type=”text”>.

class wtforms.widgets.TimeInput(input_type=None)[source]

Render a <input type=”time”>.

class wtforms.widgets.URLInput(input_type=None)[source]

Render an <input type=”url”>.

class wtforms.widgets.WeekInput(input_type=None)[source]

Render an <input type=”week”>.

Widget-Building Utilities

These utilities are used in WTForms widgets to help render HTML and also in order to work along with HTML templating frameworks. They can be imported for use in building custom widgets as well.

wtforms.widgets.html_params(**kwargs)[source]

Generate HTML attribute syntax from inputted keyword arguments.

The output value is sorted by the passed keys, to provide consistent output each time this function is called with the same parameters. Because of the frequent use of the normally reserved keywords class and for, suffixing these with an underscore will allow them to be used.

In order to facilitate the use of data- and aria- attributes, if the name of the attribute begins with data_ or aria_, then every underscore will be replaced with a hyphen in the generated attribute.

>>> html_params(data_attr='user.name', aria_labeledby='name')
'data-attr="user.name" aria-labeledby="name"'
In addition, the values True and False are special:
  • attr=True generates the HTML compact output of a boolean attribute, e.g. checked=True will generate simply checked

  • attr=False will be ignored and generate no output.

>>> html_params(name='text1', id='f', class_='text')
'class="text" id="f" name="text1"'
>>> html_params(checked=True, readonly=False, name="text1", abc="hello")
'abc="hello" checked name="text1"'
Changelog

Changed in version 3.0: aria_ args convert underscores to hyphens like data_ args.

Changed in version 2.2: data_ args convert all underscores to hyphens, instead of only the first one.

WTForms uses MarkupSafe to escape unsafe HTML characters before rendering. You can mark a string using markupsafe.Markup to indicate that it should not be escaped.

Custom widgets

Widgets, much like validators, provide a simple callable contract. Widgets can take customization arguments through a constructor if needed as well. When the field is called or printed, it will call the widget with itself as the first argument and then any additional arguments passed to its caller as keywords. Passing the field is done so that one instance of a widget might be used across many field instances.

The widget contract

A widget is any callable with the signature widget(field, **kwargs) that returns the rendered HTML. The return value should be a markupsafe.Markup instance; otherwise templating engines with autoescape enabled will escape the markup and the user will see the raw HTML tags instead of the rendered widget.

Inside the widget, the following field attributes are commonly used:

  • field.id and field.name — the rendered id/name attributes.

  • field.label — a Label instance, callable to render a <label> tag.

  • field.errors — list of validation errors after form.validate().

  • field._value() — the string representation of the current value, used for the value= attribute of inputs.

  • field.iter_choices() — for SelectField and similar; yields Choice objects with value, label, selected and render_kw.

To assemble the HTML, use html_params() for attribute strings, markupsafe.Markup to mark the result as safe, and markupsafe.escape() for any user-supplied content interpolated into the HTML:

from markupsafe import Markup, escape
from wtforms.widgets import html_params

Subclassing a built-in widget

The lightest customization is to extend an existing widget and post-process its output or its kwargs. Here is a widget that renders a text field with an extra CSS class when the field has errors:

class MyTextInput(TextInput):
    def __init__(self, error_class='has_errors'):
        super().__init__()
        self.error_class = error_class

    def __call__(self, field, **kwargs):
        if field.errors:
            existing = kwargs.pop('class', '') or kwargs.pop('class_', '')
            kwargs['class'] = f'{self.error_class} {existing}'.strip()
        return super().__call__(field, **kwargs)

Writing a widget from scratch

A widget does not have to be a class — any callable will do. Here is a widget that renders a SelectMultipleField as a collection of <input type=”checkbox”> controls:

from markupsafe import Markup, escape
from wtforms.widgets import html_params

def select_multi_checkbox(field, ul_class='', **kwargs):
    kwargs.setdefault('type', 'checkbox')
    field_id = kwargs.pop('id', field.id)
    html = [f'<ul {html_params(id=field_id, class_=ul_class)}>']
    for choice in field.iter_choices():
        choice_id = f'{field_id}-{choice.value}'
        options = dict(
            kwargs,
            name=field.name,
            value=choice.value,
            id=choice_id,
            checked=choice._selected,
        )
        html.append(f'<li><input {html_params(**options)}> ')
        html.append(f'<label for="{choice_id}">{escape(choice.label)}</label></li>')
    html.append('</ul>')
    return Markup(''.join(html))

class TestForm(Form):
    tester = SelectMultipleField(choices=my_choices, widget=select_multi_checkbox)

widget versus option_widget

For fields that wrap a collection of options (such as SelectField, RadioField and their multiple-choice variants), two extension points exist:

  • widget renders the whole field at once (the <select> element, the <ul> of radios, etc.).

  • option_widget renders a single option when the field is iterated. This is useful when you want to keep the default container but change how each option is displayed. See Solving Specific Problems for an example using ListWidget together with CheckboxInput as the option_widget.