Fields

Fields are responsible for data conversion and validation.

Field definitions

Fields are defined as members on a form in a declarative fashion:

import formidable as f

class MyForm(f.Form):
    title = f.TextField(min_length=2, max_length=10)
    content = f.TextField(max_length=200, required=False)

When a form is instantiated, a copy of each field is made with all the parameters specified in the definition. Each field instance maintains its own field data and settings.

Custom filters/validators

A field "filter" is a function that primarily transforms the input data before it is assigned as the field's value, though it can also be used for validation.

A field "validator" is a function that primarily checks if the value can be saved, though it can also transform the value before saving it.

Each field has its own internal filter and validators, but you can add custom ones by adding to the form methods named filter_fieldname and/or validate_fieldname.

Filters

Filter flow Filter flow

These methods receive the field's current value and must return a value (either the same or a transformed one).

class MyForm(f.Form):
    name = f.TextField()

    def filter_name(self, value):
        # Make any value lowercase
        return value.lower() if value else value

Remember to check if the value exists (is not None) before operating on it.

Validators

Validate flow Validate flow

To indicate that a value is not valid, raise a ValueError exception with the error code as the first argument

class MyForm(f.Form):
    name = f.TextField()

    def validate_name(self, value):
        # Validate it contains an "e"
        if "e" not in (value or ""):
            raise ValueError("invalid")

        return value

You can read more about error codes and messages in the "Custom error messages" page.

Render methods

While you can always write your HTML by hand using the field attributes discussed later, using these methods is the most practical way to render your forms.

label()

Renders the field as an HTML <label> element. Adds a for attribute pointing to the field's ID.

label(
    text: str | None = None,
    **attrs: Any
) -> str
ArgumentDescription
text

The text to display inside the label. If None, uses the field's name.

**attrs

Additional HTML attributes to include in the label element.

Example:

>>> import formidable as f
>>> field = f.TextField()

>>> print(field.label("My label"))
<label for="f-123abc">My label</label>

>>> print(field.label("My label", class_="text-sm"))
<label for="f-123abc" class="text-sm">My label</label>

error_tag()

If the field has an error, renders the field's error message as an HTML element..

error_tag(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the error element.

Example:

>>> import formidable as f
>>> field = f.TextField()
>>> field.error = "required"

>>> print(field.error_tag())
<div id="f-123abc-error" class="field-error">This field is required</div>

>>> print(field.label("My label", class_="text-red-500"))
<div id="f-123abc-error" class="text-red-500">This field is required</div>

text_input()

Renders the field as an HTML <input type="text"> element.

text_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the text input element.

Example:

>>> import formidable as f
>>> field = f.TextField()

>>> print(field.text_input())
<input type="text" id="f-123abc" name="field_name" value="field_value" required />

# With an error
>>> field.error = "required"
>>> print(field.text_input())
<input type="text" id="f-123abc" name="field_name" value="field_value"
    aria-invalid="true" aria-errormessage="f-123abc-error" required />

textarea()

Renders the field as an HTML <textarea> element.

textarea(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the textarea element.

Example:

>>> import formidable as f
>>> field = f.TextField()

>>> print(field.textarea())
<textarea id="f-123abc" name="field_name" required></textarea>

# With an error
>>> field.error = "required"
>>> print(field.textarea())
<textarea id="f-123abc" name="field_name" aria-invalid="true"
    aria-errormessage="f-123abc-error" required></textarea>

select()

Renders the field as an HTML <select> element. If the field supports multiple selections, the multiple attribute will be added automatically.

select(
    options: collections.abc.Iterable[tuple[str, str]],
    **attrs: Any
) -> str
ArgumentDescription
options

A list of tuples representing the options for the select element. Each tuple should contain the option value and display text. If the field's value matches an option's value, that option will be rendered as selected.

**attrs

Additional HTML attributes to include in the select element.

Example:

>>> import formidable as f

>>> field = f.TextField()
>>> options = [("val1", "Option 1"), ("val2", "Option 2"), ("val3", "Option 3")]
>>> field.value = "val2"
>>> print(field.select(options))
<select id="f-123abc" name="field_name" required>
<option value="val1">Option 1</option>
<option value="val2" selected>Option 2</option>
<option value="val3">Option 3</option>
</select>

# With multiple selection
>>> field = f.ListField()
>>> field.value = ["val1", "val3"]
>>> print(field.select(options))
<select id="f-123abc" name="field_name" multiple required>
<option value="val1" selected>Option 1</option>
<option value="val2">Option 2</option>
<option value="val3" selected>Option 3</option>
</select>

checkbox()

Renders the field as an HTML <input type="checkbox"> element.

checkbox(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the checkbox input element.

A check box allowing single values to be selected/deselected. If the field's value is truthy, the checkbox will be rendered as checked.

Example:

>>> import formidable as f
>>> field = f.BooleanField()

>>> print(field.checkbox())
<input type="checkbox" id="f-123abc" name="field_name" />

# When checked
>>> field.value = True
>>> print(field.checkbox())
<input type="checkbox" id="f-123abc" name="field_name" checked />

# With an error
>>> field.error = "required"
>>> print(field.checkbox())
<input type="checkbox" id="f-123abc" name="field_name" checked
    aria-invalid="true" aria-errormessage="f-123abc-error" />

radio()

Renders the field as an HTML <input type="radio"> element.

radio(
    radio_value: str,
    **attrs: Any
) -> str
ArgumentDescription
radio_value

The value attribute for this radio button. If it matches the field's value, the radio button will be rendered as checked.

**attrs

Additional HTML attributes to include in the radio input element.

A radio button, allowing a single value to be selected out of multiple choices with the same name value.

Example:

>>> import formidable as f
>>> field = f.TextField()

>>> print(field.radio("option1"))
<input type="radio" id="f-123abc" name="field_name" value="option1" />

# When selected
>>> field.value = "option1"
>>> print(field.radio("option1"))
<input type="radio" id="f-123abc" name="field_name" value="option1" checked />

file_input()

Renders the field as an HTML <input type="file"> element.

file_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the file input element.

This is a control that lets the user select a file. Use the accept attribute to define the types of files that the control can select.


hidden_input()

Renders the field as an HTML <input type="hidden"> element.

hidden_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the hidden input element.

This is a control that is not displayed but whose value is submitted to the server.


password_input()

Renders the field as an HTML <input type="password"> element.

password_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the password input element.

A single-line text input whose value is obscured. Will alert user if site is not secure.


More controls

color_input()

Renders the field as an HTML <input type="color"> element.

color_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the color input element.

This is a control for specifying a color. Opens a color picker when active in supporting browsers.


date_input()

Renders the field as an HTML <input type="date"> element.

date_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the date input element.

This is a control for entering a date (year, month, and day, with no time). Opens a date picker or numeric wheels for year, month, and day when active in supporting browsers. active in supporting browsers.


datetime_input()

Renders the field as an HTML <input type="datetime-local"> element.

datetime_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the datetime input element.

This is a control for entering a date and time, with no time zone. Opens a date picker or numeric wheels for date- and time-components when active in supporting browsers.


email_input()

Renders the field as an HTML <input type="email"> element.

email_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the email input element.

This is a control for editing an email address. Looks like a text input, but has relevant keyboard in supporting browsers and devices with dynamic keyboards.


month_input()

Renders the field as an HTML <input type="month"> element.

month_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the month input element.

This is a control for entering a month and year, with no time zone.


number_input()

Renders the field as an HTML <input type="number"> element.

number_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the number input element.

This is a control for entering a number. Displays a spinner and adds default validation. Displays a numeric keypad in some devices with dynamic keypads.


range_input()

Renders the field as an HTML <input type="range"> element.

range_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the range input element.

This is a control for entering a number whose exact value is not important.

Displays as a range widget defaulting to the middle value. Used in conjunction min and max to define the range of acceptable values.


search_input()

Renders the field as an HTML <input type="search"> element.

search_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the search input element.

A single-line text input for entering search strings. Line-breaks are automatically removed from the input value. May include a delete icon in supporting browsers that can be used to clear the field.

Displays a search icon instead of enter key on some devices with dynamic keypads.


tel_input()

Renders the field as an HTML <input type="tel"> element.

tel_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the tel input element.

This is a control for entering a telephone number. Displays a telephone keypad in some devices with dynamic keypads.


time_input()

Renders the field as an HTML <input type="time"> element.

time_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the time input element.

This is a control for entering a time value with no time zone.


url_input()

Renders the field as an HTML <input type="url"> element.

url_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the url input element.

This is a control entering a URL. Looks like a text input, but has relevant keyboard in supporting browsers and devices with dynamic keyboards.


week_input()

Renders the field as an HTML <input type="week"> element.

week_input(
    **attrs: Any
) -> str
ArgumentDescription
**attrs

Additional HTML attributes to include in the week input element.

This is a control for entering a date consisting of a week-year number and a week number with no time zone.


Field attributes/properties

These attributes are the most low-level API of the fields. Use them when you need to write the HTML of your forms manually.

Name Description
id Autogenerated value intended to connect the label with the input field, improving the accessibility of the HTML form.
name The name of the field that must be used in the HTML form. In a simple form it will be the same as in the form declaration, but for subforms or nested forms, it will have a prefix.
value The current value of the field. Could be None.
error An error code (or None) like "required" or "invalid".
error_args Optional extra details for the error (if there is one).
error_message A "human-readable" version of the error, generated with the error code, the error_args, and the form's messages dictionary.