Extensions

WTForms ships with a number of extensions that make it easier to work with other frameworks and libraries, such as Django.

Appengine

WTForms now includes support for AppEngine fields as well as auto-form generation.

Model Forms

See the module docstring for examples on how to use model_form().

wtforms.ext.appengine.db.model_form(model, base_class=Form, only=None, exclude=None, field_args=None, converter=None)

Creates and returns a dynamic wtforms.Form class for a given db.Model class. The form class can be used as it is or serve as a base for extended form classes, which can then mix non-model related fields, subforms with other model forms, among other possibilities.

Parameters:
  • model – The db.Model class to generate a form for.
  • base_class – Base form class to extend from. Must be a wtforms.Form subclass.
  • only – An optional iterable with the property names that should be included in the form. Only these properties will have fields.
  • exclude – An optional iterable with the property names that should be excluded from the form. All other properties will have fields.
  • field_args – An optional dictionary of field names mapping to keyword arguments used to construct each field object.
  • converter – A converter to generate the fields based on the model properties. If not set, ModelConverter is used.

Datastore-backed Fields

class wtforms.ext.appengine.fields.ReferencePropertyField(default field arguments, reference_class=None, label_attr=None, allow_blank=False, blank_text=u'')

A field for db.ReferenceProperty. The list items are rendered in a select.

class wtforms.ext.appengine.fields.StringListPropertyField(default field arguments)

A field for db.StringListProperty. The list items are rendered in a textarea.

class wtforms.ext.appengine.fields.GeoPtPropertyField(default field arguments)

Dateutil

For better date-time parsing using the python-dateutil package, wtforms.ext.dateutil provides a set of fields to use to accept a wider range of date input.

class wtforms.ext.dateutil.fields.DateTimeField(default field arguments, parse_kwargs=None, display_format='%Y-%m-%d %H:%M')

DateTimeField represented by a text input, accepts all input text formats that dateutil.parser.parse will.

Parameters:
  • parse_kwargs – A dictionary of keyword args to pass to the dateutil parse() function. See dateutil docs for available keywords.
  • display_format – A format string to pass to strftime() to format dates for display.
class wtforms.ext.dateutil.fields.DateField(default field arguments, parse_kwargs=None, display_format='%Y-%m-%d')

Same as the DateTimeField, but stores only the date portion.

Django

This extension provides templatetags to make it easier to work with Django templates and WTForms’ html attribute rendering. It also provides a generator for automatically creating forms based on Django ORM models.

Templatetags

Django templates does not allow arbitrarily calling functions with parameters, making it impossible to use the html attribute rendering feature of WTForms. To alleviate this, we provide a templatetag.

Adding wtforms.ext.django to your INSTALLED_APPS will make the wtforms template library available to your application. With this you can pass extra attributes to form fields similar to the usage in jinja:

{% load wtforms %}

{% form_field form.username class="big_text" onclick="do_something()" %}

Note By default, using the {{ form.field }} syntax in django models will be auto-escaped. To avoid this happening, use Django’s {% autoescape off %} block tag or use WTForms’ form_field template tag.

Model forms

wtforms.ext.django.orm.model_form(model, base_class=Form, only=None, exclude=None, field_args=None, converter=None)

Create a wtforms Form for a given Django model class:

from wtforms.ext.django.orm import model_form
from myproject.myapp.models import User
UserForm = model_form(User)
Parameters:
  • model – A Django ORM model class
  • base_class – Base form class to extend from. Must be a wtforms.Form subclass.
  • only – An optional iterable with the property names that should be included in the form. Only these properties will have fields.
  • exclude – An optional iterable with the property names that should be excluded from the form. All other properties will have fields.
  • field_args – An optional dictionary of field names mapping to keyword arguments used to construct each field object.
  • converter – A converter to generate the fields based on the model properties. If not set, ModelConverter is used.

model_form() attempts to glean as much metadata as possible from inspecting the model’s fields, and will even attempt to guess at what validation might be wanted based on the field type. For example, converting an EmailField will result in a TextField with the email() validator on it. if the blank property is set on a model field, the resulting form field will have the optional() validator set.

Just like any other Form, forms created by ModelForm can be extended via inheritance:

UserFormBase = model_form(User)

class UserForm(UserFormBase):
    new_pass     = PasswordField('', [validators.optional(), validators.equal_to('confirm_pass')])
    confirm_pass = PasswordField()

When combined with form iteration, model_form is a handy way to generate dynamic CRUD forms which update with added fields to the model. One must be careful though, as it’s possible the generated form fields won’t be as strict with validation as a hand-written form might be.

ORM-backed fields

While linking data to most fields is fairly easy, making drop-down select lists using django ORM data can be quite repetetive. To this end, we have added some helpful tools to use the django ORM along with wtforms

class wtforms.ext.django.fields.QuerySetSelectField(default field args, queryset=None, label_attr='', allow_blank=False, blank_text=u'')

Given a QuerySet either at initialization or inside a view, will display a select drop-down field of choices. The data property actually will store/keep an ORM model instance, not the ID. Submitting a choice which is not in the queryset will result in a validation error.

Specifying label_attr in the constructor will use that property of the model instance for display in the list, else the model object’s __str__ or __unicode__ will be used.

If allow_blank is set to True, then a blank choice will be added to the top of the list. Selecting this choice will result in the data property being None. The label for the blank choice can be set by specifying the blank_text parameter.

class ArticleEdit(Form):
    title    = TextField()
    column   = QuerySetSelectField(label_attr='title', allow_blank=True)
    category = QuerySetSelectField(queryset=Category.objects.all())

def edit_article(request, id):
    article = Article.objects.get(pk=id)
    form = ArticleEdit(obj=article)
    form.column.queryset = Column.objects.filter(author=request.user)

As shown in the above example, the queryset can be set dynamically in the view if needed instead of at form construction time, allowing the select field to consist of choices only relevant to the user.

class wtforms.ext.django.fields.ModelSelectField(default field args, model=None, label_attr='', allow_blank=False, blank_text=u'')

Like a QuerySetSelectField, except takes a model class instead of a queryset and lists everything in it.

SQLAlchemy

This extension provides SelectField integration with SQLAlchemy ORM models, similar to those in the Django extension.

ORM-backed fields

These fields are provided to make it easier to use data from ORM objects in your forms.

def enabled_categories():
    return Category.query.filter_by(enabled=True)

class BlogPostEdit(Form):
    title    = TextField()
    blog     = QuerySelectField(get_label='title')
    category = QuerySelectField(query_factory=enabled_categories, allow_blank=True)

def edit_blog_post(request, id):
    post = Post.query.get(id)
    form = ArticleEdit(obj=post)
    # Since we didn't provide a query_factory for the 'blog' field, we need
    # to set a dynamic one in the view.
    form.blog.query = Blog.query.filter(Blog.author == request.user).order_by(Blog.name)
class wtforms.ext.sqlalchemy.fields.QuerySelectField(default field args, query_factory=None, get_pk=None, get_label=None, allow_blank=False, blank_text=u'')

Will display a select drop-down field to choose between ORM results in a sqlalchemy Query. The data property actually will store/keep an ORM model instance, not the ID. Submitting a choice which is not in the query will result in a validation error.

This field only works for queries on models whose primary key column(s) have a consistent string representation. This means it mostly only works for those composed of string, unicode, and integer types. For the most part, the primary keys will be auto-detected from the model, alternately pass a one-argument callable to get_pk which can return a unique comparable key.

The query property on the field can be set from within a view to assign a query per-instance to the field. If the property is not set, the query_factory callable passed to the field constructor will be called to obtain a query.

Specify get_label to customize the label associated with each option. If a string, this is the name of an attribute on the model object to use as the label text. If a one-argument callable, this callable will be passed model instance and expected to return the label text. Otherwise, the model object’s __str__ or __unicode__ will be used.

If allow_blank is set to True, then a blank choice will be added to the top of the list. Selecting this choice will result in the data property being None. The label for this blank choice can be set by specifying the blank_text parameter.

class wtforms.ext.sqlalchemy.fields.QuerySelectMultipleField(default field args, query_factory=None, get_pk=None, get_label=None, allow_blank=False, blank_text=u'')

Very similar to QuerySelectField with the difference that this will display a multiple select. The data property will hold a list with ORM model instances and will be an empty list when no value is selected.

If any of the items in the data list or submitted form data cannot be found in the query, this will result in a validation error.