CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-wtforms

Form validation and rendering for Python web development.

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

widgets.mddocs/

Widgets and Rendering

HTML rendering system with customizable widgets for different input types, from basic text inputs to complex multi-select components and custom layouts. Widgets handle the conversion of form fields into HTML markup with proper attributes and styling.

Capabilities

Widget Utilities

Core utilities for HTML generation and attribute handling.

def html_params(**kwargs) -> str:
    """
    Generate HTML attributes from keyword arguments.
    
    Parameters:
    - **kwargs: Attribute name-value pairs
    
    Returns:
    str: HTML attribute string
    
    Example:
    html_params(id="myfield", class_="form-control", required=True)
    # Returns: 'id="myfield" class="form-control" required'
    """

Base Widget Classes

Foundation widget classes that other widgets inherit from.

class Widget:
    """
    Base widget class for HTML rendering.
    """
    def __call__(self, field, **kwargs) -> str:
        """
        Render field as HTML.
        
        Parameters:
        - field: Field instance to render
        - **kwargs: Additional HTML attributes
        
        Returns:
        str: HTML markup
        """

class Input(Widget):
    """
    Base class for HTML input elements.
    
    Parameters:
    - input_type: HTML input type attribute
    """
    def __init__(self, input_type=None): ...
    def __call__(self, field, **kwargs) -> str: ...

Text Input Widgets

Widgets for various text input types.

class TextInput(Input):
    """
    Standard text input widget.
    Renders: <input type="text" />
    """
    def __init__(self): ...

class PasswordInput(Input):
    """
    Password input widget (hides input value).
    Renders: <input type="password" />
    
    Parameters:
    - hide_value: Whether to hide value in HTML (default: True)
    """
    def __init__(self, hide_value=True): ...

class HiddenInput(Input):
    """
    Hidden input widget.
    Renders: <input type="hidden" />
    """
    def __init__(self): ...

class TextArea(Widget):
    """
    Multi-line textarea widget.
    Renders: <textarea></textarea>
    """
    def __call__(self, field, **kwargs) -> str: ...

HTML5 Input Widgets

Modern HTML5 input types with enhanced validation and user experience.

class EmailInput(Input):
    """
    HTML5 email input widget.
    Renders: <input type="email" />
    """
    def __init__(self): ...

class URLInput(Input):
    """
    HTML5 URL input widget.
    Renders: <input type="url" />
    """
    def __init__(self): ...

class SearchInput(Input):
    """
    HTML5 search input widget.
    Renders: <input type="search" />
    """
    def __init__(self): ...

class TelInput(Input):
    """
    HTML5 telephone input widget.
    Renders: <input type="tel" />
    """
    def __init__(self): ...

class NumberInput(Input):
    """
    HTML5 number input widget.
    Renders: <input type="number" />
    
    Parameters:
    - step: Step value for numeric input
    - min: Minimum value
    - max: Maximum value
    """
    def __init__(self, step=None, min=None, max=None): ...

class RangeInput(Input):
    """
    HTML5 range input widget.
    Renders: <input type="range" />
    
    Parameters:
    - step: Step value for range input
    """
    def __init__(self, step=None): ...

class ColorInput(Input):
    """
    HTML5 color input widget.
    Renders: <input type="color" />
    """
    def __init__(self): ...

Date and Time Widgets

Widgets for date and time input with HTML5 support.

class DateInput(Input):
    """
    HTML5 date input widget.
    Renders: <input type="date" />
    """
    def __init__(self): ...

class TimeInput(Input):
    """
    HTML5 time input widget.
    Renders: <input type="time" />
    """
    def __init__(self): ...

class DateTimeInput(Input):
    """
    HTML5 datetime input widget.
    Renders: <input type="datetime" />
    """
    def __init__(self): ...

class DateTimeLocalInput(Input):
    """
    HTML5 datetime-local input widget.
    Renders: <input type="datetime-local" />
    """
    def __init__(self): ...

class MonthInput(Input):
    """
    HTML5 month input widget.
    Renders: <input type="month" />
    """
    def __init__(self): ...

class WeekInput(Input):
    """
    HTML5 week input widget.
    Renders: <input type="week" />
    """
    def __init__(self): ...

Choice and Selection Widgets

Widgets for selecting from multiple options.

class CheckboxInput(Input):
    """
    Checkbox input widget.
    Renders: <input type="checkbox" />
    """
    def __init__(self): ...

class RadioInput(Input):
    """
    Radio input widget.
    Renders: <input type="radio" />
    """
    def __init__(self): ...

class Select(Widget):
    """
    Select dropdown widget.
    Renders: <select><option>...</option></select>
    
    Parameters:
    - multiple: Whether to allow multiple selections
    """
    def __init__(self, multiple=False): ...
    def __call__(self, field, **kwargs) -> str: ...

class Option(Widget):
    """
    Option element for Select widget.
    Renders: <option value="...">label</option>
    """
    def __call__(self, field, **kwargs) -> str: ...

File Input Widgets

Widgets for file uploads.

class FileInput(Input):
    """
    File input widget.
    Renders: <input type="file" />
    
    Parameters:
    - multiple: Whether to allow multiple file selection
    """
    def __init__(self, multiple=False): ...

Button and Submit Widgets

Widgets for form submission and actions.

class SubmitInput(Input):
    """
    Submit button widget.
    Renders: <input type="submit" />
    """
    def __init__(self): ...

Container Widgets

Widgets for organizing and grouping multiple fields.

class ListWidget(Widget):
    """
    Container widget that renders fields as list items.
    Used for RadioField and CheckboxField groups.
    
    Parameters:
    - html_tag: HTML tag for container (default: "ul")
    - prefix_label: Whether to put label before input (default: True)
    """
    def __init__(self, html_tag="ul", prefix_label=True): ...
    def __call__(self, field, **kwargs) -> str: ...

class TableWidget(Widget):
    """
    Container widget that renders fields in table format.
    Used for FormField to organize nested forms.
    
    Parameters:
    - with_table_tag: Whether to wrap in <table> tag (default: True)
    """
    def __init__(self, with_table_tag=True): ...
    def __call__(self, field, **kwargs) -> str: ...

Widget Usage Examples

Basic Widget Usage

from wtforms import Form, StringField
from wtforms.widgets import TextInput, TextArea

class MyForm(Form):
    # Default widget (TextInput)
    name = StringField('Name')
    
    # Custom widget
    bio = StringField('Biography', widget=TextArea())
    
    # Widget with custom attributes
    email = StringField('Email', 
        widget=TextInput(),
        render_kw={'placeholder': 'Enter your email', 'class': 'form-control'}
    )

# Render fields
form = MyForm()
print(form.name())  # <input id="name" name="name" type="text" value="" />
print(form.bio())   # <textarea id="bio" name="bio"></textarea>
print(form.email()) # <input class="form-control" id="email" name="email" placeholder="Enter your email" type="text" value="" />

HTML5 Input Widgets

from wtforms import Form, StringField, IntegerField, DateField
from wtforms.widgets import EmailInput, NumberInput, DateInput, ColorInput

class ProfileForm(Form):
    email = StringField('Email', widget=EmailInput())
    website = StringField('Website', widget=URLInput())
    age = IntegerField('Age', widget=NumberInput(min=13, max=120))
    birth_date = DateField('Birth Date', widget=DateInput())
    favorite_color = StringField('Favorite Color', widget=ColorInput())
    
    # Range input with custom attributes
    satisfaction = IntegerField('Satisfaction', 
        widget=RangeInput(step=1),
        render_kw={'min': 1, 'max': 10}
    )

# Generated HTML includes HTML5 validation attributes
form = ProfileForm()
print(form.age())  # <input id="age" max="120" min="13" name="age" type="number" value="" />

Select and Choice Widgets

from wtforms import Form, SelectField, SelectMultipleField
from wtforms.widgets import Select

class PreferencesForm(Form):
    # Default Select widget
    country = SelectField('Country', choices=[
        ('us', 'United States'),
        ('ca', 'Canada')
    ])
    
    # Multiple selection
    languages = SelectMultipleField('Languages', 
        choices=[
            ('en', 'English'),
            ('es', 'Spanish'),
            ('fr', 'French')
        ],
        widget=Select(multiple=True)
    )

form = PreferencesForm()
print(form.country())
# <select id="country" name="country">
#   <option value="us">United States</option>
#   <option value="ca">Canada</option>
# </select>

print(form.languages())
# <select id="languages" multiple name="languages">
#   <option value="en">English</option>
#   <option value="es">Spanish</option>
#   <option value="fr">French</option>
# </select>

Radio Button Lists

from wtforms import Form, RadioField
from wtforms.widgets import ListWidget, RadioInput

class SurveyForm(Form):
    rating = RadioField('Rating', 
        choices=[
            ('1', 'Poor'),
            ('2', 'Fair'),
            ('3', 'Good'),
            ('4', 'Very Good'),
            ('5', 'Excellent')
        ],
        widget=ListWidget(prefix_label=False),
        option_widget=RadioInput()
    )

form = SurveyForm()
print(form.rating())
# <ul id="rating">
#   <li><input id="rating-0" name="rating" type="radio" value="1"> <label for="rating-0">Poor</label></li>
#   <li><input id="rating-1" name="rating" type="radio" value="2"> <label for="rating-1">Fair</label></li>
#   ...
# </ul>

File Upload Widgets

from wtforms import Form, FileField, MultipleFileField
from wtforms.widgets import FileInput

class UploadForm(Form):
    single_file = FileField('Upload File', widget=FileInput())
    multiple_files = MultipleFileField('Upload Files', 
        widget=FileInput(multiple=True)
    )

form = UploadForm()
print(form.single_file())   # <input id="single_file" name="single_file" type="file" />
print(form.multiple_files()) # <input id="multiple_files" multiple name="multiple_files" type="file" />

Custom Widget Development

from wtforms.widgets import Widget
from wtforms import Form, StringField

class StarRatingWidget(Widget):
    """Custom star rating widget."""
    
    def __call__(self, field, **kwargs):
        kwargs.setdefault('id', field.id)
        html = []
        
        # Add star rating HTML
        html.append(f'<div class="star-rating" id="{field.id}">')
        for i in range(1, 6):
            checked = 'checked' if field.data == str(i) else ''
            html.append(f'''
                <input type="radio" name="{field.name}" value="{i}" {checked} />
                <label for="{field.id}-{i}">★</label>
            ''')
        html.append('</div>')
        
        return ''.join(html)

class ReviewForm(Form):
    rating = StringField('Rating', widget=StarRatingWidget())
    comment = StringField('Comment')

form = ReviewForm()
print(form.rating())  # Custom star rating HTML

Widget with Bootstrap Classes

from wtforms import Form, StringField, SelectField, SubmitField
from wtforms.widgets import TextInput, Select, SubmitInput

class BootstrapForm(Form):
    name = StringField('Name', 
        widget=TextInput(),
        render_kw={'class': 'form-control', 'placeholder': 'Enter your name'}
    )
    
    category = SelectField('Category',
        choices=[('tech', 'Technology'), ('science', 'Science')],
        widget=Select(),
        render_kw={'class': 'form-select'}
    )
    
    submit = SubmitField('Submit',
        widget=SubmitInput(),
        render_kw={'class': 'btn btn-primary'}
    )

form = BootstrapForm()
print(form.name())
# <input class="form-control" id="name" name="name" placeholder="Enter your name" type="text" value="" />

Conditional Widget Selection

from wtforms import Form, StringField
from wtforms.widgets import TextInput, TextArea

class DynamicForm(Form):
    content = StringField('Content')
    
    def __init__(self, use_textarea=False, *args, **kwargs):
        super().__init__(*args, **kwargs)
        
        # Choose widget based on condition
        if use_textarea:
            self.content.widget = TextArea()
        else:
            self.content.widget = TextInput()

# Usage
short_form = DynamicForm(use_textarea=False)
long_form = DynamicForm(use_textarea=True)

print(short_form.content())  # <input type="text" ... />
print(long_form.content())   # <textarea>...</textarea>

Widget Attribute Manipulation

from wtforms import Form, StringField
from wtforms.widgets import html_params

class CustomForm(Form):
    username = StringField('Username')

# Render with custom attributes
form = CustomForm()
field = form.username

# Method 1: Using render_kw
field.render_kw = {'class': 'form-control', 'data-validate': 'true'}
print(field())

# Method 2: Passing attributes directly
print(field(class_='form-control', placeholder='Enter username'))

# Method 3: Using html_params utility
attrs = html_params(id=field.id, name=field.name, class_='form-control', required=True)
print(f'<input {attrs} />')

Nested Form Widgets

from wtforms import Form, StringField, FormField
from wtforms.widgets import TableWidget

class AddressForm(Form):
    street = StringField('Street')
    city = StringField('City')
    zipcode = StringField('Zip Code')

class UserForm(Form):
    name = StringField('Name')
    address = FormField(AddressForm, widget=TableWidget())

form = UserForm()
print(form.address())
# <table>
#   <tr><th><label for="address-street">Street</label></th>
#       <td><input id="address-street" name="address-street" type="text" value="" /></td></tr>
#   <tr><th><label for="address-city">City</label></th>
#       <td><input id="address-city" name="address-city" type="text" value="" /></td></tr>
#   ...
# </table>

Widget Theming and Styling

from wtforms import Form, StringField, SelectField, BooleanField
from wtforms.widgets import CheckboxInput

class ThemedForm(Form):
    # Material Design theme
    name = StringField('Name', render_kw={
        'class': 'mdc-text-field__input',
        'placeholder': ' '  # Required for Material Design
    })
    
    # Tailwind CSS theme
    category = SelectField('Category', 
        choices=[('a', 'Option A'), ('b', 'Option B')],
        render_kw={
            'class': 'block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500'
        }
    )
    
    # Custom checkbox styling
    agree = BooleanField('I agree', 
        widget=CheckboxInput(),
        render_kw={
            'class': 'h-4 w-4 text-indigo-600 focus:ring-indigo-500 border-gray-300 rounded'
        }
    )

form = ThemedForm()
# Each field renders with appropriate CSS classes

Install with Tessl CLI

npx tessl i tessl/pypi-wtforms

docs

csrf.md

fields.md

forms.md

i18n.md

index.md

validation.md

widgets.md

tile.json