Table Of Contents
Extensions¶
WTForms ships with a number of extensions that make it easier to work with other frameworks and libraries, such as Django.
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()
category = QuerySelectField(query_factory=enabled_categories, allow_blank=True)
def edit_blog_post(request, id):
post = Post.query.get(id)
form = ArticleEdit(obj=post)
form.blog.query = Blog.query.filter(Blog.author == request.user).order_by(Blog.name)
