Form validation and rendering for Python web development.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive collection of form field types for handling different data types including text, numbers, dates, choices, files, and complex nested structures. All fields inherit from the base Field class and provide data processing, validation, and HTML rendering.
Base classes and infrastructure that all fields inherit from.
class Field:
"""
Base class for all form fields.
Parameters:
- label: Field label text or Label object
- validators: List/tuple of validator instances
- filters: List/tuple of data filters (functions that transform data)
- description: Help text for the field
- id: HTML id attribute (auto-generated if not provided)
- default: Default value for the field
- widget: Widget instance for HTML rendering
- render_kw: Dict of extra attributes for widget rendering
- name: Field name (usually set automatically)
"""
def __init__(self, label=None, validators=None, filters=(),
description="", id=None, default=None, widget=None,
render_kw=None, name=None, _form=None, _prefix="",
_translations=None, _meta=None): ...
def validate(self, form, extra_validators=()) -> bool:
"""Run validation chain, returns True if valid."""
def process(self, formdata, data=None, extra_filters=None):
"""Process raw form data into field data."""
def populate_obj(self, obj, name):
"""Set attribute on object with field data."""
def __call__(self, **kwargs) -> str:
"""Render field as HTML string."""
def gettext(self, string) -> str:
"""Get translated string."""
def ngettext(self, singular, plural, n) -> str:
"""Get translated string with pluralization."""
# Properties
data: any # Processed field value
raw_data: list # Raw input data from form
errors: tuple # Validation error messages
process_errors: tuple # Processing error messages
label: Label # Label object
flags: Flags # Widget flags for HTML attributes
validators: tuple # Validator instances
widget: Widget # Widget for rendering
class UnboundField:
"""
Unbound field for class-level field definitions.
Parameters:
- field_class: Field class to instantiate
- *args, **kwargs: Arguments for field constructor
"""
def __init__(self, field_class, *args, **kwargs): ...
def bind(self, name, form, **kwargs) -> Field: ...
class Label:
"""HTML form label wrapper."""
def __init__(self, field_id, text): ...
def __call__(self, text=None, **kwargs) -> str: ... # Render label HTML
class Flags:
"""Container for field flags/attributes used by widgets."""
def __getattr__(self, name): ...
def __setattr__(self, name, value): ...Basic text input fields for string data with various input types and constraints.
class StringField(Field):
"""
Basic text input field.
Widget: TextInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class TextAreaField(Field):
"""
Multi-line text input field.
Widget: TextArea()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class PasswordField(Field):
"""
Password input field (doesn't render current value for security).
Widget: PasswordInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class HiddenField(Field):
"""
Hidden form field.
Widget: HiddenInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class SearchField(Field):
"""
HTML5 search input field.
Widget: SearchInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class TelField(Field):
"""
HTML5 telephone input field.
Widget: TelInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class URLField(Field):
"""
HTML5 URL input field.
Widget: URLInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class EmailField(Field):
"""
HTML5 email input field.
Widget: EmailInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class ColorField(Field):
"""
HTML5 color input field.
Widget: ColorInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...Fields for handling numeric data with appropriate validation and widgets.
class IntegerField(Field):
"""
Integer input field with numeric validation.
Widget: NumberInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class FloatField(Field):
"""
Float input field with numeric validation.
Widget: NumberInput(step="any")
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class DecimalField(Field):
"""
Decimal input field with precision control.
Widget: NumberInput(step="any")
Parameters:
- places: Number of decimal places (None for no rounding)
- rounding: Decimal rounding mode
- use_locale: Use locale-specific number formatting
- number_format: Custom number format string
"""
def __init__(self, label=None, validators=None, places=None,
rounding=None, use_locale=False, number_format=None, **kwargs): ...
class IntegerRangeField(Field):
"""
HTML5 range input for integers.
Widget: RangeInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class DecimalRangeField(Field):
"""
HTML5 range input for decimal values.
Widget: RangeInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...Fields for boolean values and form submission.
class BooleanField(Field):
"""
Boolean checkbox field.
Widget: CheckboxInput()
Parameters:
- false_values: Iterable of values considered False (default: (False, "false", ""))
"""
def __init__(self, label=None, validators=None, false_values=None, **kwargs): ...
class SubmitField(Field):
"""
Submit button field.
Widget: SubmitInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...Fields for handling date and time data with format parsing.
class DateTimeField(Field):
"""
DateTime input field with format parsing.
Widget: DateTimeInput()
Parameters:
- format: strptime format string for parsing (default: "%Y-%m-%d %H:%M:%S")
"""
def __init__(self, label=None, validators=None, format="%Y-%m-%d %H:%M:%S", **kwargs): ...
class DateField(Field):
"""
Date input field with format parsing.
Widget: DateInput()
Parameters:
- format: strptime format string for parsing (default: "%Y-%m-%d")
"""
def __init__(self, label=None, validators=None, format="%Y-%m-%d", **kwargs): ...
class TimeField(Field):
"""
Time input field with format parsing.
Widget: TimeInput()
Parameters:
- format: strptime format string for parsing (default: "%H:%M")
"""
def __init__(self, label=None, validators=None, format="%H:%M", **kwargs): ...
class MonthField(Field):
"""
HTML5 month input field.
Widget: MonthInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class WeekField(Field):
"""
HTML5 week input field.
Widget: WeekInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class DateTimeLocalField(Field):
"""
HTML5 datetime-local input field.
Widget: DateTimeLocalInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...Fields for selecting from predefined options.
class SelectFieldBase(Field):
"""
Abstract base class for choice fields.
"""
def iter_choices(self):
"""Iterator yielding (value, label, selected, render_kw) tuples."""
def has_groups(self) -> bool:
"""Returns True if choices have optgroups."""
def iter_groups(self):
"""Iterator yielding (group_label, choices) tuples."""
class SelectField(SelectFieldBase):
"""
Select dropdown field.
Widget: Select()
Parameters:
- choices: List of (value, label) tuples or dict
- coerce: Function to coerce form data (default: str)
- validate_choice: Whether to validate selection is in choices (default: True)
"""
def __init__(self, label=None, validators=None, coerce=str, choices=None,
validate_choice=True, **kwargs): ...
class SelectMultipleField(SelectField):
"""
Multiple selection field.
Widget: Select(multiple=True)
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class RadioField(SelectField):
"""
Radio button list field.
Widget: ListWidget(prefix_label=False)
Option Widget: RadioInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...Fields for file uploads.
class FileField(Field):
"""
File upload field.
Widget: FileInput()
"""
def __init__(self, label=None, validators=None, **kwargs): ...
class MultipleFileField(FileField):
"""
Multiple file upload field.
Widget: FileInput(multiple=True)
"""
def __init__(self, label=None, validators=None, **kwargs): ...Fields for handling nested forms and dynamic lists.
class FormField(Field):
"""
Embed another form as a field.
Widget: TableWidget()
Parameters:
- form_class: Form class to embed
- separator: Separator for nested field names (default: "-")
"""
def __init__(self, form_class, label=None, validators=None, separator="-", **kwargs): ...
class FieldList(Field):
"""
Dynamic list of repeated fields.
Widget: ListWidget()
Parameters:
- unbound_field: UnboundField instance for list entries
- min_entries: Minimum number of entries (default: 0)
- max_entries: Maximum number of entries (default: None)
- separator: Separator for indexed field names (default: "-")
- default: Default value factory (default: ())
"""
def __init__(self, unbound_field, label=None, validators=None,
min_entries=0, max_entries=None, separator="-", default=(), **kwargs): ...
def append_entry(self, data=None) -> Field:
"""Add new entry to the list, returns the new field."""
def pop_entry(self) -> Field:
"""Remove and return the last entry."""from wtforms import Form, StringField, IntegerField, validators
class ProductForm(Form):
name = StringField('Product Name', [
validators.DataRequired(),
validators.Length(max=100)
])
price = DecimalField('Price', [
validators.NumberRange(min=0),
validators.DataRequired()
], places=2)
description = TextAreaField('Description')
# Access field data
form = ProductForm(formdata=request.form)
if form.validate():
product_name = form.name.data
product_price = form.price.dataclass UserForm(Form):
country = SelectField('Country', choices=[
('us', 'United States'),
('ca', 'Canada'),
('mx', 'Mexico')
])
languages = SelectMultipleField('Languages', choices=[
('en', 'English'),
('es', 'Spanish'),
('fr', 'French')
])
notification_method = RadioField('Notifications', choices=[
('email', 'Email'),
('sms', 'SMS'),
('none', 'None')
])
# Dynamic choices
def get_categories():
return [(c.id, c.name) for c in Category.query.all()]
class ArticleForm(Form):
title = StringField('Title')
category = SelectField('Category', coerce=int)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.category.choices = get_categories()class EventForm(Form):
name = StringField('Event Name')
start_date = DateField('Start Date')
start_time = TimeField('Start Time')
end_datetime = DateTimeField('End Date & Time')
# Custom date format
custom_date = DateField('Custom Date', format='%d/%m/%Y')
# Access datetime data
form = EventForm(formdata=request.form)
if form.validate():
event_start = datetime.combine(
form.start_date.data,
form.start_time.data
)class AddressForm(Form):
street = StringField('Street')
city = StringField('City')
zipcode = StringField('Zip Code')
class ContactForm(Form):
name = StringField('Name')
# Embedded form
address = FormField(AddressForm)
# Dynamic list of phone numbers
phone_numbers = FieldList(StringField('Phone'), min_entries=1)
# Process nested data
form = ContactForm(formdata=request.form)
if form.validate():
contact_name = form.name.data
street_address = form.address.street.data
all_phones = [phone.data for phone in form.phone_numbers]class EmailListField(Field):
"""Custom field that accepts comma-separated email addresses."""
def process_formdata(self, valuelist):
if valuelist:
self.data = [email.strip() for email in valuelist[0].split(',')]
else:
self.data = []
def validate(self, form, extra_validators=()):
super().validate(form, extra_validators)
for email in self.data:
if not re.match(r'^[^@]+@[^@]+\.[^@]+$', email):
raise ValidationError(f'Invalid email: {email}')
class NewsletterForm(Form):
subject = StringField('Subject')
recipients = EmailListField('Recipients')class DocumentForm(Form):
title = StringField('Document Title')
file = FileField('Upload File', [validators.DataRequired()])
attachments = MultipleFileField('Additional Files')
# Process file uploads
form = DocumentForm(formdata=request.form, files=request.files)
if form.validate():
uploaded_file = form.file.data # FileStorage object
filename = uploaded_file.filename
uploaded_file.save(f'/uploads/{filename}')
# Handle multiple files
for attachment in form.attachments.data:
if attachment.filename:
attachment.save(f'/uploads/{attachment.filename}')Install with Tessl CLI
npx tessl i tessl/pypi-wtforms